python|python之numpy库--科学计算基础库必学(一)

numpy是Python一个非常强大的拓展库,专门用来处理数组和矩阵运算,并且提供数组和矩阵相关的大量内置函数库,其运行效率非常高,而专门进行数据分析的pandas库也是基于numpy的数据底层。可以说在处理大量数据的场景下,numpy有着绝对的应用场景,一般主要应用于以下场合:

  1. 处理数组和矩阵运算等基础运算
  2. 线性代数、傅里叶变换、大量随机数生成等基础应用场景
  3. 与scipy和matplotlib库组合使用,处理科学计算相关问题,可以基本替代matlab,并且因为其可以与Python其他库(网络和数据库等)完美融合,其潜力可能更大。
下面开始系统性介绍numpy库,掌握好该库是掌握pandas 、scipy甚至后续运用大数据分析和人工智能等相关框架的基础,如果掌握好了,会对后续学习有很大的帮助。
一、numpy基础 1.1 ndarray介绍 ndarray是numpy的核心概念,它是一系列同类型数据组成的数组,可以是一维或多维数组,可以认为是同类型数据的存储容器,不过相较于Python自身的列表、字典等对象数据类型,其要求存储在其中的数据类型需要相同,且运算效率极高。
而在后续要接触到的pandas中,Series类型数据可以近似认为就是ndarray,而pandas的DataFrame则本质是多个ndarray组成,其核心还是ndarray,只不过在此基础上进行了很多特性的封装,让更加适合处理类似excel表格类的数据集。
1.2 ndarray数组对象属性
属性 说明 示意
ndarray.ndim 秩:即轴的数量或维度的数量,dim即dimention ndarray.ndim→2
ndarray.shape 形状:数组的维度,对于矩阵,n 行 m 列 ndarray.shape→(n,m)
ndarray.size 数量:即数组或矩阵的元素总个数,为n*m ndarray.size→n*m
ndarray.dtype 数据类型:即该数组内元素的数据类型 ndarray.dtype→object
ndarray.itemsize 元素大小:即该数组内元素占据内存大小,字节单位 ndarray.itemsize→8
ndarray.flags 该数组的内存信息,一般用不到
ndarray.real 数组元素的实部:即由数组内每个元素实部组成的相同形状的数组
ndarray.imag 数组元素的虚部:即由数组内每个元素虚部组成的相同形状的数组
ndarray.data 包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。
1.3 numpy数据类型 numpy可以认为是一种数据容器,在该容器内可以存放相同数据类型的数据,接下来会开始介绍numpy支持的常见数据类型,首先讲解numpy的dtype对象,因为numpy借由该对象来定义数据类型。也可以认为以下将要介绍的数据类型是dtype对象的实例。
1.3.1 dtype对象
#数据类型对象(numpy.dtype 类的实例)用来描述与数组对应的内存区域是如何使用,主要描述数据类型、大小等属性 #numpy已经内置(定义)了很多常用的数据类型对象实例,可以直接拿来使用,不过也可按照自己的需要,使用基础的数据类型来构造自己独特的数据类型对象实例,并赋值给array的dtype #以下是dtype对象的构造函数 numpy.dtype( object,#要转换为的数据类型对象,可以是基础内置数据类型、Python对象或其组合 align,#如果为 true,填充字段使其类似 C 的结构体。一般很少用到 copy ##复制 dtype 对象 ,如果为 false,则是对内置数据类型对象的引用,一般很少用到 )

1.3.2 内置数据类型
numpy已经根据实际需要,内置封装了很多数据类型,无需自己再次定义,直接用即可,以下为常用的数据类型及其用法
数据类型及取值范围 类型代码(字符) 类型说明 示意
int8(-128 to 127)
uint8(0 to 255)
i1、u1 有符号和无符号的8位(1字节)整型 dtype='i1'、dtype='u1'
dtype=np.int8、dtype=np.uint8
int16(-32768 to 32767)
uint16(0 to 65535)
i2、u2 有符号和无符号的16位(2字节)整型 dtype='i2'、dtype='u2'
dtype=np.int16、dtype=np.uint16
int32
uint32
i3、u3 有符号和无符号的32位(3字节)整型 dtype='i3'、dtype='u3'
dtype=np.int32、dtype=np.uint32
int64
uint64
i4、u4 有符号和无符号的64位(4字节)整型 dtype='i4'、dtype='u4'
dtype=np.int64、dtype=np.uint64
float16 f2 半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位
dtype='f2'或dtype=np.float16
float32 f4或f 标准精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位 dtype='f4'或dtype='f'或dtype=np.float32
float64 f8或d 双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位 dtype='f8'或dtype='d'或dtype=np.float64
float128 f16或g 扩展精度浮点数 dtype='f16'或dtype='g'或dtype=np.float128
complex64
complex128
complex256
c8
c16
c32
32位浮点数分别表示实部和虚部,共64位的虚数
64位浮点数分别表示实部和虚部,共128位的虚数
128位浮点数分别表示实部和虚部,共256位的虚数
dtype='c8'或dtype=np.complex64
dtype='c16'或dtype=np.complex128
dtype='c32'或dtype=np.complex256
bool ? 布尔型数据 dtype=bool或dtype='?'或dtype=np.bool
object O python对象类型 dtype='O'或dtype=np.object
string S或a 固定长度字符串数据类型(每个字符1个字节)
如要创建一个10个字符的字符串,则语法为S10
dtype='S'或dtype=str或dtype='a'(自动调节字符串长度)
dtype='S3'(字符串长度固定,多出的会截断)

unicode U 固定长度字符串数据类型(每个字符的字节数由所在平台或系统决定)
如要创建一个10个字符的字符串,则语法为S10
dtype='U'或dtype=np.unicode_(自动调节字符串长度)
dtype='U3'(字符串长度固定,多出的会截断)
datetime64 M 日期时间格式,在使用datetime64字符指定时,也可指定日期时间格式的单位(Y、M、D、h、m、s)
Y代表只截取到年,M代表截取到月,D代表截取到日,依次类推
dtype='M'或dtype=np.datetime64(均根据数据自动找寻合适的单位)
dtype='datetime64[M]'(强制截取到月)
1.3.3 自定义结构化数据类型
#numpy的dtype对象,不仅可以使用内置的数据类型,还可按照实际需要,基于内置数据类型,创建结构化的数据类型,并在创建具体array时使用 #下面创建一个关于人的结构化数据类型,包括姓名、性别、是否入职、出生日期四个字段 import numpy as np people=np.dtype([ ('name','S20'), ('gender','S10'), ('entry','bool'), ('birthday','datetime64[D]',) ]) #使用people结构化数据类型创建array peoples=np.array( [ ('dennis','female','1','2020-10-20'), ('jacky','male','0','2018-10-20'), ('tony','female','1','2000-10-20') ], dtype=people ) #访问其中某个字段 people['name'] →['dennis','jacky','tony']

1.3.4 复用其他ndarray数据对象
#也可以直接复用其他array的dtype对象,并创建新的array import numpy as np arr1=np.array( [1,2,3], dtype=np.float64 ) arr2=np.array( [4,5,6], dtype=arr1.dtype )

二、数组创建 2.1 使用array构造器创建 2.1.1 概述
#一般使用array构造函数创建ndarray import numpy as np numpy.array( object, #传入列表、元组来创建一维数组,或列表、元组的嵌套创建多维数组 dtype = None, #设置数组元素的数据类型,可以是内置的数据类型,也可是自定义的结构化数据类型 copy = True,#设置传入的对象是否需要复制,默认是True,如果设置为False,则会直接引用,一般用不到 order = None, #设置创建数组的样式,C为行方向,F为列方向,A为任意方向(默认),一般无需显示设置 subok = False, #默认返回一个与基类类型一致的数组,暂时还未用到过 ndmin = 0 #指定生成数组的最小维度,如果传入的object维度没达到最小维度,则会自定转变为最小维度的数组 )

2.1.2 具体创建
最基础的是使用np.array构造函数创建ndarray,下面展示具体创建方法
#1、创建一维数组 import numpy as np np.array( [1,2,3,4,5] #或(1,2,3,4,5) )#2、创建多维数组 np.array([ [1,2,3], [4,5,6] ]) #会创建一个2*3的数组,即维数为2的数组,其他高维数组,依次类推#3、创建一个显示指定数据类型的数组,比如复数 np.array( [1,2,3,4,5], dtype='c8' )

2.2 使用存量数据创建 2.2.1 概述
#可以直接从存量的数据创建数组,需要使用asarray函数 #整体功能与arrray类似 numpy.asarray( a, #任意形式的输入参数,可以是,列表, 列表的元组, 元组, 元组的元组, 元组的列表,多维数组 dtype = None,#数组的数据类型,枚举与array函数类似,不再赘述 order = None #一般用不到 )

2.2.2 从存量的数组或元组创建
import numpy as np a=[1,2,3,4] b=(2,2,2) c=[(1,2,),(2,2)] np.asarray(a) → array([1, 2, 3, 4]) np.asarray(b) → array([2, 2, 2]) np.asarray(c) → array([[1, 2], [2, 2]])

2.2.3 从可迭代对象创建
#也可以通过传入python的迭代对象,来创建数组 numpy.fromiter( iterable, #python的可迭代对象 dtype, #数据类型,不再赘述,必填 count=-1 #读取的数据数量,默认为-1,读取所有数据 )list=range(1,100,2) it=iter(list) np.fromiter(it,float)

2.3 从数值范围创建 2.3.1 numpy.arange创建
#可类似使用Python的range函数,创建序列数组 numpy.arange( start, #序列开始值 stop, #序列结束值,一般不包括该值 step, #步长,即序列之间数值差 dtype#数据类型,不再赘述 )import numpy as np np.arrange(1,10,2,dtype=float)

2.3.2 numpy.linspace创建一维等差数组
#可直接创建一维的由等差数列组成的数组,相较于arrange,该函数是指定数列范围、数列需要包含的数值个数,然后系统会自动生成包含对应数量的等差序列,两者应用场景不同 np.linspace( start, #数列的开始值 stop, #数列的结束值,如果endpoint为true,该值包含于数列中,默认包含 num=50, #数列的数值个数,即要生成的等步长的样本数量,默认为50 endpoint=True, #该值为 true 时,数列中包含stop值,反之不包含,默认是True。 retstep=False, #如果为 True 时,生成的数组中会显示间距,反之不显示。 dtype=None #不再赘述 )import numpy as np np.linspace(10,100,20)

2.3.3 numpy.logspace创建一维等等比数组
#可直接创建一维的由等比数列组成的数组,可指定开始和结束数值,以及数列包含的数字数量 np.logspace( start, #序列的起始值 stop, #序列的终止值为:base ** stop。如果endpoint为true,该值包含于数列中 num=50, #要生成的等步长的样本数量,默认为50 endpoint=True, #该值为 true 时,数列中中包含stop值,反之不包含,默认是True。 base=10.0,#对数 log 的底数。 dtype=None #不再赘述 )import numpy as np np.logspace(1,5,5,base=2)

2.4 内置特殊矩阵&数组的创建 2.4.1 创建指定大小的空数组
#numpy内置了较多在线性代数中可能比较常用的矩阵或数组,比如空数组 #空数组即数据或矩阵内的元素没有进行初始化赋值,其元素可能是任何值 numpy.empty( shape, #元组或列表格式,指定需创建的数组或矩阵的大小,或者形状 dtype = float,#不再赘述 order = 'C' #一般用不到 )import numpy as np np.empty([2,3])

2.4.2 创建指定大小的零数组
#可创建元素全为0(近似为0)的数组或矩阵 numpy.zeros( shape, dtype = float, order = 'C' )import numpy as np np.zeros([2,3])

2.4.3 创建指定大小的一数组
#可创建元素全为1(近似为1)的数组或矩阵 numpy.ones( shape, dtype = float, order = 'C' )import numpy as np np.ones([2,3])

2.4.4 创建对角矩阵数组
#可创建对角线矩阵 np.eye( N, #指定对角矩阵的行数 M=None, #指定对角矩阵的列数,默认与N相等 k=0, #对角线的索引,默认为0,即斜对角,如果赋予正值或负值,则会相对向右上或左下移动 dtype=float,#不再赘述 order='C' )import numpy as np np.eye(5)

2.4.5 创建随机数组
#1、创建指定形状的,服从 X~N(0,1) 的正态分布随机数组 np.random.randn(2,3)#创建一个2*3的符合正态分布的随机数组#2、创建指定形状的,随机分布整型数组或矩阵 randint( low, #随机整数的下限,可以是整数或者数组形式的列表,如果是列表,则将直接决定最终生成的矩阵形状 high=None, #随机数的上限,可以是整数或者数组形式的列表,如果是列表,则将与low一起,决定最终生成的矩阵形状,会按照广播机制生成,此时,指定size基本无效 size=None, #一般用于在Low和high均为整数,此时该参数指定最终生成矩阵的形状 dtype=int #不再赘述 ) np.random.randint(2,10,(3,3))#此种用法最常见

三、数组访问和查询 3.1 数组访问 3.1.1 切片和索引访问
#因矩阵或数组,其实本质是由列表组成,故也可以使用与访问Python列表元素相同的方式对数组进行切片和索引访问 import numpy as np a=np.arange(1,21).reshape(4,5) #创建一个4*5的矩阵 #a为: array([[ 1,2,3,4,5], [ 6,7,8,9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20]]) a[m,n] #m、n即可以是索引,又可以是切片,也可以是由索引组成的列表#1、使用索引切片访问和提取数组的一部分 a[1:3,0:5:2] #会提取2到3行,1到6列每隔1列取一列,并组成一个2*3矩阵 array([[ 6,8, 10], [11, 13, 15]])#2、提取指定的行、列 a[2] #提取第3行 array([11, 12, 13, 14, 15]) a[:,2]#提取第2列,并组成一维数组 array([ 3,8, 13, 18])#3、提取指定的元素 a[1,1] #提取第2行的第二列元素#4、一维及更高维,同理,比如提取shape为3*4*5的矩阵,则即a[k,m,n],其中京k、m、n即可以是索引值,也可以是由索引值构成的切片#5、切片中省略号的用法 #当要提取某一整行或整列时,其效果与:完全相同 a[:,1] #等同于a[...,1] a[1,:] #等同于a[1,...]#6、切片对象简介 s=slice(1,3) a[s] #等同于a[1:3]

3.1.2 花式索引访问
#花式索引,其实就是指利用整数数组进行索引,对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素(类似索引访问);如果目标是二维数组,那么就是对应下标的行(类似直接取对应的行) #花式索引主要有以下几种情况,最终结果一般都是另外一个数组 import numpy as np #1、原数组为一维数组,传入1个一维数组作为索引 a=np.array([1,2,3,4,5,6]) a[[1,2,3]] #得到a的第2、3、4个元素并组成一个新的一维数组#2、原数组为二维数组,传入1个一维数组作为索引 a=np.array([ [1,2,3], [4,5,6], [7,8,9] ]) a[[1,2]] #得到a的第2和第3行组成的2*3数组#3、原数组为多维数组,传入多个一维数组作为索引 a=np.array([ [1,2,3], [4,5,6], [7,8,9] ]) a[[0,1],[0,1]] #得到a的第1行第1列、第2行第2列两个元素组成的一维数组#4、原数组为多维数组,传入多个一维数组作为索引,且使用ix_函数 #pandas内的iloc索引方式,其本质即ix_的索引方式 a=np.array([ [1,2,3], [4,5,6], [7,8,9] ]) a[np.ix_([0,1],[0,1])] #得到由a的第1、2行,第1、2列交叉组成的2*2矩阵 array([[1, 2], [4, 5]])

3.1.3 布尔索引访问 了解清楚布尔索引,会对后续学习pandas相关操作有较大帮助
#布尔索引,可以使用布尔表达式(条件表达式)来检索出某个数组符合指定条件的元素,并返回由这些元素组成的一维数组 #布尔索引在理解pandas相关条件检索操作时,很有用,可以说pandas的条件检索,本质就是布尔索引 #其本质的运算逻辑即对数组进行遍历,找出满足条件的元素对应的索引值,最后返回索引值对应的元素 import numpy as np a=np.arange(2,10).reshape(2,4) a[(a>2)&(a<8)] #会返回大于2且小于8的元组组成的一维数组#其他比如非运算(~),或运算(|)也均可以使用并组成更加复杂的条件表达式

3.2 遍历和迭代 3.2.1 遍历行、列
import numpy as np a=np.array([ [1,2,3], [4,5,6], [7,8,9] ]) #1、通过for语句,遍历以上数组的所有行 for row in a: print(row) #会逐行输出以上数组 #2、通过for语句,遍历以上数组的所有列 for i in a.T: print(i) #先将a进行转置,然后再逐行遍历转置后的数组

3.2.2 遍历元素
#如果需要遍历某数组的元素,则需要使用nditer函数,该函数提供了访问numpy元素的多种方式 #下面只罗列最为常见的操作 np.nditer( a, #需遍历的数组 order ='C', #遍历的方向或顺序,C代表从上到下逐行遍历,F代表从左到右逐列遍历 op_flags= ‘readwrite’, #可设置在遍历的同时,可以直接修改原数组内对应元素的值,默认只读 flags =['external_loop'] # )#以下均使用下面的数据 import numpy as np a=np.array([ [1,2,3], [4,5,6], [7,8,9] ])#1、按行遍历元素 for i in np.nditer(a,order='C'): print(i,end=',') #输出结果如下: 1,2,3,4,5,6,7,8,9,#2、按列遍历元素 for i in np.nditer(a,order='F'): print(i,end=',') #输出结果如下: 1,4,7,2,5,8,3,6,9,#3、遍历的同时,修改元素,对大于6的元素,统一加1 for i in np.nditer(a,order='C',op_flags=['readwrite']): if i>6: i+=1 #最后a数组变为如下: array([[ 1,2,3], [ 4,5,6], [ 8,9, 10]])#4、广播迭代,如果两个数组是可广播的,nditer 组合对象能够同时迭代它们 b=np.arange(10,26).reshape(4,4) for i,j in np.nditer([a,b]): print(i,j)

3.3 排序
#主要对指定数组进行排序,一般是从小到大的排序方法,此时需要用到sort函数,该函数会返回排序后的数组 numpy.sort( a, #待排序的数组 axis, #指定排序的轴方向,axis=0 按列排序,axis=1 按行排序 kind, #指定排序的方法,默认'quicksort',一般无需设置 order #如果数组包含字段,则是要排序的字段,一般用不到 )import numpy as np a=np.array([ [1,3,2], [4,8,6], [7,10,9] ]) np.sort(a) #输出结果如下: array([[ 1,2,3], [ 4,6,8], [ 7,9, 10]])

3.4 条件抽取&筛选 以下方法,均是返回对应元素在原数组的索引,如果需要返回对应的元素,则可以使用索引引用
3.4.1 最大值最小值元素
#numpy.argmax() 和 numpy.argmin() import numpy as np a=np.array([ [ 1,3,2], [ 4,8,6], [ 7, 10,9] ]) #1、指定数轴的最大值,会按照指定轴方向,返回沿着该轴最大值对应的索引 np.argmax( a,#需找寻最大值的数组 axis =0 #0指按行方向,1指按列方向 ) np.argmax(a,axis=0) #输入为如下 array([2, 2, 2])#1、指定数轴的最小值,会按照指定轴方向,返回沿着该轴最小值对应的索引 np.argmin( a,#需找寻最小值的数组 axis =0 #0指按行方向,1指按列方向 ) np.argmin(a,axis=0) #输入为如下 array([0, 0, 0])

3.4.2 非零元素
#numpy.nonzero() 函数返回输入数组中非零元素的索引。 import numpy as np a=np.array([ [ 1,3,2], [ 4,8,6], [ 7, 10,9] ])np.nonzero(a) #会返回非零元素构成的索引,如果传入的数组维数大于1,则会返回对应维数个数的由索引组成的数组,返回值为: (array([0, 0, 0, 1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2, 0, 1, 2]))b=np.nonzero(a) a[b] #会返回由非零元素组成的一维数组 array([ 1,3,2,4,8,6,7, 10,9])

3.4.3 按布尔条件筛选
#numpy.where(),用来找寻满足指定条件元素对应的索引值 import numpy as np a=np.array([ [ 1,3,2], [ 4,8,6], [ 7, 10,9] ]) np.where(a>4) #输出结果如下: (array([1, 1, 2, 2, 2]), array([1, 2, 0, 1, 2]))b=np.where(a>4) a[b] #输出为 array([ 8,6,7, 10,9])

【python|python之numpy库--科学计算基础库必学(一)】

    推荐阅读