1、NumPy(Numerical Python)概述
1.1 NumPy是什么?
- 一个开源的python科学计算库
- 使用NumPy可以方便的使用数组、矩阵进行计算
- 具有广播功能函数
- 包含线性代数、傅里叶变换、随机数生成等大量函数
1.2 对于同样的数值计算任务,使用NumPy比直接Python代码实现,优点:
- 代码更简洁: NumPy直接以数组、矩阵为粒度计算并且支撑大量的数学函数,而python需要用for循环从底层实现;
- 性能更高效: NumPy的数组存储效率和输入输出计算性能,比Python使用List或者嵌套List好很多;
●注: NumPy的数据存储和Python原生的List是不一样的;
●注: NumPy的大部分代码都是C语言实现的,这是NumPy比纯Python代码高效的原因。
1.3 NumPy是Python各种数据科学类库的基础库:
- 比如: Scipy,Scikit-Learn、TensorFlow,pandas等
2、Ndarray(n-dimensional array)对象
NumPy定义了一个n维数组对象,简称ndarray对象,它是一个一系列相同类型元素组成的数组集合。数组中的每个元素都占有大小相同的内存块。
ndarray 对象采用了数组的索引机制,将数组中的每个元素映射到内存块上,并且按照一定的布局对内存块进行排列(行或列)。
ndarray 内部由以下内容组成:
一个指向数据(内存或内存映射文件中的一块数据)的指针。
数据类型或 dtype,描述在数组中的固定大小值的格子。
一个表示数组形状(shape)的元组,表示各维度大小的元组。
一个跨度元组(stride),其中的整数指的是为了前进到当前维度下一个元素需要"跨过"的字节数。
创建方式:
NumPy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
名称 描述 object 数组或嵌套的数列 dtype 数组元素的数据类型,可选 copy 对象是否需要复制,可选 order 创建数组的样式,C为行方向,F为列方向,A为任意方向(默认) subok 默认返回一个与基类类型一致的数组 ndmin 指定生成数组的最小维度
3、NumPy数组属性
NumPy 数组的维数称为秩(rank),秩就是轴的数量,即数组的维度,一维数组的秩为 1,二维数组的秩为 2,以此类推。(维数——秩——轴数)
在 NumPy中,每一个线性的数组称为是一个轴(axis),也就是维度(dimensions)。比如说,二维数组相当于是两个一维数组,其中第一个一维数组中每个元素又是一个一维数组。所以一维数组就是 NumPy 中的轴(axis),第一个轴相当于是底层数组,第二个轴是底层数组里的数组。而轴的数量——秩,就是数组的维数。
很多时候可以声明 axis。axis=0,表示沿着第 0 轴进行操作,即对每一列进行操作;axis=1,表示沿着第1轴进行操作,即对每一行进行操作。
NumPy 的数组中比较重要 ndarray 对象属性有:
属性 | 说明 |
---|---|
ndarray.ndim | 秩,即轴的数量或维度的数量 |
ndarray.shape | 数组的维度,对于矩阵,n 行 m 列 |
ndarray.size | 数组元素的总个数,相当于 .shape 中 n*m 的值 |
ndarray.dtype | ndarray 对象的元素类型 |
ndarray.itemsize | ndarray 对象中每个元素的大小,以字节为单位 |
ndarray.flags | ndarray 对象的内存信息 |
ndarray.real | ndarray元素的实部 |
ndarray.imag | ndarray 元素的虚部 |
ndarray.data | 包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。 |
测试:
a = np.arange(24)
print('a:',a)
print('a.ndim:',a.ndim)
b = np.array([[1,2,3],[4,5,6]])
print('b.shape:',b.shape)
b.shape = (3,2) #也可以使用reshape
print('改变后的b.shape:',b.shape)
print('a.size:',a.size)
print('a.dtype:',a.dtype)
x = np.array([1,2,3,4,5], dtype = np.int8)
y = np.array([1,2,3,4,5], dtype = np.float64)
print('x.itemsize:',x.itemsize)
print('y.itemsize:',y.itemsize)
print('a.flags:',a.flags)
print('a.real:',a.real)
print('a.imag:',a.imag)
print('a.data:',a.data)
结果:
附 ndarray.flags 返回 ndarray 对象的内存信息所包含的属性:
属性 | 描述 |
---|---|
C_CONTIGUOUS © | 数据是在一个单一的C风格的连续段中 |
F_CONTIGUOUS (F) | 数据是在一个单一的Fortran风格的连续段中 |
OWNDATA (O) | 数组拥有它所使用的内存或从另一个对象中借用它 |
WRITEABLE (W) | 数据区域可以被写入,将该值设置为 False,则数据为只读 |
ALIGNED (A) | 数据和所有元素都适当地对齐到硬件上 |
UPDATEIFCOPY (U) | 这个数组是其它数组的一个副本,当这个数组被释放时,原数组的内容将被更新 |
4、NumPy创建数组
创建数组的几种常见机制:
NumPy
中定义的原生数组创建函数- 使用Python中类数组对象创建
NumPy
数组
4.1 NumPy
中定义的原生数组创建函数
方法 | 描述 | 参数含义 |
---|---|---|
numpy.arange([start, ]stop, [step, ]dtype=None, *, like=None) | 返回给定间隔内的均匀间隔的值。 | |
numpy.linspace(start,stop,num=50, endpoint=True, retstep=False, dtype=None, axis=0) | 返回指定间隔内的等间隔数字。 | num:要生成的等步长的样本数量,默认为50;endpoint:该值为 true 时,数列中包含stop值,反之不包含,默认是True; |
numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0) | 返回在对数刻度上均匀间隔的数字。 | base:底数。 |
numpy.empty(shape, dtype=float, order=‘C’, *, like=None) | 返回给定形状和类型的新数组,而不初始化条目。 | shape:新数组的形状大小;order:默认:’ C '是在内存中按行主(C样式)还是列主(Fortran样式)顺序存储多维数据。 |
numpy.empty_like(prototype, dtype=None, order=‘K’, subok=True, shape=None) | 返回与给定数组具有相同形状和类型的新数组。 | prototype:创建的新数组定义了和这个对象相同的形状和数据类型;order:存储顺序,'C’表示C-order,'F’表示F-order,'K’表示遵循a的顺序;subok:如果为True,则新创建的数组将使用a的子类类型,否则它将是基类数组;shape:重新指定结果的形状。 |
numpy.ones(shape, dtype=None, order=‘C’, *, like=None) | 返回给定形状和类型的新数组,其中填充了 1。 | |
numpy.ones_like(a, dtype=None, order=‘K’, subok=True, shape=None) | 返回一个与给定数组具有相同形状和类型的数组。 | |
numpy.zeros(shape, dtype=float, order=‘C’, *, like=None) | 返回一个给定形状和类型的新数组,用零填充。 | |
numpy.zeros_like(a, dtype=None, order=‘K’, subok=True, shape=None) | 返回一个与给定数组具有相同形状和类型的零数组。 | |
numpy.full(shape, fill_value, dtype=None, order=‘C’, *, like=None) | 返回给定形状和类型的新数组,填充fill_value。 | |
numpy.full_like(a, fill_value, dtype=None, order=‘K’, subok=True, shape=none) | 返回与给定数组具有相同形状和类型的完整数组。 | |
numpy.eye(N, M=None, k=0, dtype=<class ‘float’>, order=‘C’, *, like=None) | 返回一个二维数组,对角线上有 2,其他地方有 <>。 | N:输出数组的行数;M:输出数组的列数,如果为None,默认等与N;K:0表示主对角线,正数表示上对角线,负数表示下对角线; |
numpy.identity(n, dtype=None, *, like=None) | 返回标识数组。(默认返回对角线为1的n×n数组) | N:输出数组的行数; |
测试:
print('arange:', np.arange(0, 9, 1, dtype=int))
print('linspace默认数据类型:', np.linspace(0, 9, 10).dtype)
tmp = np.linspace(0, 9, 10, dtype=int, retstep=True)
print('linspace:', tmp)
tmp2 = np.logspace(1, 2, 2, base=2, dtype=int)
print('logspace:', tmp2)
tmp3 = np.empty([2,3], dtype=int, order='C')
print('empty:', tmp3)
a = np.zeros([2,3], dtype=int)
tmp4 = np.empty_like(a)
print('empty_like:', tmp4)
tmp5 = np.ones([2,3])
print('ones:', tmp5)
a = np.ones([2,3])
tmp6 = np.ones_like(a)
print('ones_like:', tmp6)
tmp7 = np.zeros([2,3])
print('zeros:', tmp7)
tmp8 = np.zeros_like(np.zeros([2,3]))
print('zeros_like:', tmp8)
tmp9 = np.full([2,3], 1)
print('full:', tmp9)
tmp10 = np.full_like(np.zeros([2,3]), 1)
print('full_like:', tmp10)
tmp11 = np.eye(4, M=5, dtype=float)
tmp12 = np.eye(4, k=1, dtype=float)
print('eye:', tmp11)
print('eye:', tmp12)
tmp13 = np.identity(5, dtype=int)
print('identity:', tmp13)
结果:
4.2 使用Python中类数组对象创建 NumPy
数组
方法 | 描述 | 参数含义 |
---|---|---|
numpy.array(object, dtype=None,*,copy=True, order=‘K’,subok=False, ndmin=0,like=None) | 创建一个数组。 | object:array-like结构的数值数据对象,如果是标量,返回包含该对象的0维数组;copy:值为True,则复制对象;ndmin:指定生成的数组应具有的最小维度数。为了满足这一要求,将根据需要对其形状进行预处理; |
numpy.asarray(a, dtype=None,order=None, *,like=None) | 将输入转换为数组。 | |
numpy.asanyarray(a,dtype=None,order=None,*, like=None) | 将输入转换为 ndarray,但传递 ndarray 子类。 | |
numpy.asmatrix(data,* dtype=None) | 将输入解释为矩阵。 | |
numpy.copy(a, order=‘K’, subok=False) | 返回给定对象的数组副本。 |
测试:
print('一维:', np.array([1, 2, 3], ndmin=1))
print('二维:', np.array([1, 2, 3], ndmin=2))
# 'a'表示第一项,'b'表示第二项
x = np.array([(1,2),(3,4)],dtype=[('a','<i4'),('b','<i4')])
print('第一项:', x['a'])
print('第二项:', x['b'])
a = np.array([1, 2])
print('asarray:', np.asarray(a) is a)
a1 = np.array([(1.0, 2), (3.0, 4)], dtype='f4,i4')
print('asanyarray:', np.asanyarray(a1) is a1)
x = np.array([[1, 2], [3, 4]])
m = np.asmatrix(x)
x[0,0] = 5
print('asmatrix:', m)
x1 = np.array([[1, 2], [3, 4]])
print('copy:', np.copy(x))
结果:
5、NumPy切片和索引
5.1 切片
ndarray 数组可以基于 0 - n 的下标进行索引,切片对象可以通过内置的 slice 函数,并设置 start, stop 及 step 参数进行,从原数组中切割出一个新数组。
冒号 : 的解释:如果只放置一个参数,如 [2],将返回与该索引相对应的单个元素。如果为 [2:],表示从该索引开始以后的所有项都将被提取。如果使用了两个参数,如 [2:7],那么则提取两个索引(不包括停止索引)之间的项。
切片还可以包括省略号 …,来使选择元组的长度与数组的维度相同。 如果在行位置使用省略号,它将返回包含行中元素的 ndarray。
测试:
a = np.arange(10)
print('a:', a)
s = slice(2,7,2) # 从索引 2 开始到索引 7 停止,间隔为2
print ('slice(2,7,2):', a[s])
b = a[2:7:2] # 从索引 2 开始到索引 7 停止,间隔为 2
print('a[2:7:2]:', b)
x = np.array([[1,2,3],[3,4,5],[4,5,6]])
print('x:\n', x)
# 从某个索引处开始切割
print('从数组索引 a[1:] 处开始切割:')
print(x[1:])
y = np.array([[1,2,3],[3,4,5],[4,5,6]])
print ('第2列元素:', y[...,1]) # 第2列元素
print ('第2行元素:', y[1,...]) # 第2行元素
print ('第2列及剩下的所有元素:\n',y[...,1:]) # 第2列及剩下的所有元素
结果:
5.2 索引
NumPy 中的高级索引指的是使用整数数组、布尔数组或者其他序列来访问数组的元素。相比于基本索引,高级索引可以访问到数组中的任意元素,并且可以用来对数组进行复杂的操作和修改。
测试:
整数数组索引
# 整数数组索引
x = np.array([[1, 2], [3, 4], [5, 6]])
y = x[[0,1,2], [0,1,0]]
print('获取数组中 (0,0),(1,1) 和 (2,0) 位置处的元素。')
print('原数组:\n',x)
print ('获取数组中 (0,0),(1,1) 和 (2,0) 位置处的元素\n', y)
print('-----------------------')
x1 = np.array([[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]])
print('获取了 4X3 数组中的四个角的元素。 行索引是 [0,0] 和 [3,3],而列索引是 [0,2] 和 [0,2]。')
print ('原数组是:' )
print (x1)
rows = np.array([[0,0],[3,3]])
cols = np.array([[0,2],[0,2]])
y = x1[rows,cols]
print ('数组的四个角元素是:')
print (y)
print('-----------------------')
print('借助切片 : 或 … 与索引数组组合。')
a = np.array([[1,2,3], [4,5,6],[7,8,9]])
b = a[1:3, 1:3]
c = a[1:3,[1,2]]
d = a[...,1:]
print('原数组:\n',a)
print('b:\n', b)
print('c:\n', c)
print('d:\n', d)
布尔索引
# 布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。
print('获取大于 5 的元素。')
x = np.array([[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]])
print ('原数组是:')
print (x)
# 现在我们会打印出大于 5 的元素
print ('大于 5 的元素是:')
print (x[x > 5])
print('-----------------------')
print('使用 ~(取补运算符)来过滤 NaN。')
a = np.array([np.nan, 1,2,np.nan,3,4,5])
print('原数组:', a)
print ('结果:', a[~np.isnan(a)])
花式索引
# 花式索引指的是利用整数数组进行索引。
# 花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。
# 对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素,如果目标是二维数组,那么就是对应下标的行。
# 花式索引跟切片不一样,它总是将数据复制到新数组中。
print("-------读取下标对应的元素-------")
x = np.arange(9)
print('原数组:', x)
# 一维数组读取指定下标对应的元素
x2 = x[[0, 6]] # 使用花式索引
print('x[[0, 6]]:',x2)
print("-------读取下标对应的行-------")
x1=np.arange(32).reshape((8,4))
print('原数组:', x1)
# 二维数组读取指定下标对应的行
print ('x1[[4,2,1,7]]:\n', x1[[4,2,1,7]])
6、NumPy广播
广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行。
广播的规则:
- 让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加 1 补齐。
- 输出数组的形状是输入数组形状的各个维度上的最大值。
- 如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为 1 时,这个数组能够用来计算,否则出错。
- 当输入数组的某个维度的长度为 1 时,沿着此维度运算时都用此维度上的第一组值。
**简单理解:**对两个数组,分别比较他们的每一个维度(若其中一个数组没有当前维度则忽略),满足:
- 数组拥有相同形状。
- 当前维度的值相等。
- 当前维度的值有一个是 1。
测试:
print('当运算中的 2 个数组的形状不同时,numpy 将自动触发广播机制。')
a = np.array([[ 0, 0, 0],
[10,10,10],
[20,20,20],
[30,30,30]])
b = np.array([0,1,2])
print('a:\n',a)
print('b:\n',b)
print('a+b:\n',a + b)
结果:
7、NumPy迭代数组
NumPy 迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式。
迭代器最基本的任务是可以完成对数组元素的访问。
测试:
#不是使用标准 C 或者 Fortran 顺序,选择的顺序是和<数组内存>布局一致的,这样做是为了提升访问的效率,
#默认是行序优先(row-major order,或者说是 C-order)。
# a 和 a.T 的遍历顺序是一样的,也就是他们在内存中的存储顺序也是一样的,
#但是 a.T.copy(order = 'C') 的遍历结果是不同的,因为它和前两种的存储方式是不一样的,默认是按行访问。
a = np.arange(6).reshape(2,3)
print(a)
print ('\n')
print ('--------a与a.T比较--------')
print ('迭代输出元素:')
for x in np.nditer(a):
print (x, end=", " )
print ('\n')
for x in np.nditer(a.T):
print (x, end=", " )
print ('\n')
print ('--------通过参数order控制访问方式--------')
for x in np.nditer(a.T.copy(order='C')):
print (x, end=", " )
print ('\n')
for x in np.nditer(a.T, order='F'):
print (x, end=", " )
print('\n')
print ('--------通过参数op_flags修改元素--------')
for x in np.nditer(a, op_flags=['readwrite']):
x[...]=2*x
print(a)
print('\n')
print ('--------测试参数flag--------')
# flag参数的值
# c_index 可以跟踪 C 顺序的索引
# f_index 可以跟踪 Fortran 顺序的索引
# multi_index 每次迭代可以跟踪一种索引类型
# external_loop 给出的值是具有多个值的一维数组,而不是零维数组
b = np.arange(0,60,5)
b = b.reshape(3,4)
print('b:\n', b)
print('\n')
for x in np.nditer(b, flags = ['external_loop'], order = 'F'):
print (x, end=", " )
print ('\n')
print ('--------广播迭代--------')
a = np.arange(0,60,5)
a = a.reshape(3,4)
print ('第一个数组为:')
print (a)
print ('第二个数组为:')
b = np.array([1, 2, 3, 4], dtype = int)
print (b)
print ('修改后的数组为:')
for x,y in np.nditer([a,b]):
print ("%d:%d" % (x,y), end=", " )
结果:
8、NumPy数组操作
8.1 改变数组形状
方法 | 描述 | 参数含义 |
---|---|---|
numpy.reshape(a, newshape, order = ‘C’) | 在不更改数据的情况下为数组赋予新的形状。 | order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘k’ – 元素在内存中的出现顺序。 |
numpy.ravel(a, order = ‘C’) | 返回一个连续的扁平数组。 | |
numpy.ndarray.flat | 数组上的一维迭代器。 | |
numpy.ndarray.flatten(order=‘C’) | 返回折叠成一维的数组副本。 |
测试:
print('---------reshape----------')
a = np.arange(8)
print ('原始数组:')
print (a)
print ('\n')
b = a.reshape(4,2)
print ('修改后的数组:')
print (b)
print('----------flat---------')
print ('原始数组:')
for row in b:
print (row)
#对数组中每个元素都进行处理,可以使用flat属性,该属性是一个数组元素迭代器:
print ('迭代后的数组:')
for element in b.flat:
print (element)
print('----------flatten---------')
print ('展开的数组:')
print (b.flatten())
print ('\n')
print ('以 F 风格顺序展开的数组:')
print (b.flatten(order = 'F'))
print('----------ravel---------')
print ('原数组:')
print (b)
print ('\n')
print ('调用 ravel 函数之后:')
print (a.ravel())
print ('\n')
print ('以 F 风格顺序调用 ravel 函数之后:')
print (a.ravel(order = 'F'))
结果:
8.2 类转置操作
方法 | 描述 | 参数含义 |
---|---|---|
numpy.moveaxis(a, source, destination) | 将数组的轴移到新位置。 | source:int或int的序列 要移动的轴的原始位置。这些必须是唯一的;destination:int或int的序列 每个原始轴的目标位置。这些也必须是独一无二的。 |
numpy.rollaxis(a, axis, start=0) | 向后滚动指定的轴,直到其位于给定的位置。 | axis:整数 要滚动的轴。其他轴的位置相对于彼此不发生变化; |
numpy.swapaxes(a, axis1, axis2) | 互换数组的两个轴。 | |
numpy.ndarray.T | 转置数组。 | |
numpy.transpose(a, axes) | 排列数组的尺寸。 | axes:如果指定,它必须是一个元组或列表,其中包含[0,1,…,N-1]的排列,其中N是a的轴数。返回数组的第i个轴将对应于输入的轴编号的轴[i]。如果未指定,则默认为范围(a.ndim)[::-1],这将颠倒轴的顺序。 |
测试:
print('--------moveaxis----------')
x = np.zeros((3, 4, 5))
print('原数组:\n', x.shape)
print('np.moveaxis(x,0,-1).shape:\n', np.moveaxis(x,0,-1).shape)
print('np.moveaxis(x,[0,1],[-1,0]).shape:\n', np.moveaxis(x,[0,1],[-1,0]).shape)
print('--------rollaxis----------')
a = np.ones((3,4,5,6))
print('原数组:\n', a.shape)
print('np.rollaxis(a, 3, 1).shape:\n', np.rollaxis(a, 3, 1).shape)
print('np.rollaxis(a, 2).shape:\n', np.rollaxis(a, 2).shape)
print('np.rollaxis(a, 1, 4).shape:\n', np.rollaxis(a, 1, 4).shape)
print('--------swapaxes----------')
x = np.array([[[0,1],[2,3]],[[4,5],[6,7]]])
print('原数组:\n', x)
print('np.swapaxes(x,0,2):\n', np.swapaxes(x,0,2))
print('--------ndarray.T---------')
a = np.array([[1, 2], [3, 4]])
print('原数组:\n', a)
print('a.T:\n', a.T)
print('--------transpose----------')
b = np.transpose(a)
print(b)
print(np.transpose(np.ones((4,5,6)), (1, 0, 2)).shape)
print(np.transpose(np.ones((4,5,6))).shape)
结果:
8.3 更改维度数
方法 | 描述 | 参数含义 |
---|---|---|
numpy.broadcast(array1, array2) | 产生模仿广播的对象。 | |
numpy.broadcast_to(array, shape, subok=False) | 将数组广播为新形状。 | shape:所需数组的形状; |
numpy.broadcast_array(*args, **kwargs) | 互相广播任意数量的阵列。 | |
numpy.expand_dims(a, axis) | 扩展数组的形状。 | axis:int or tuple of ints; |
numpy.squeeze(a, axis) | 从数组形状中删除一维条目。 | axis:选择形状中长度为1的条目的子集。如果选择的轴的形状输入大于一,则会引发错误。 |
numpy.atleast_1d(*args) | 将输入转换为至少一维的数组。 | *args:一个或多个array; |
numpy.atleast_2d(*args) | 将输入视为至少具有二维的数组。 | |
numpy.atleast_3d(*args) | 以至少三个维度的数组形式查看输入。 |
测试:
print('--------broadcast--------')
x = np.array([[1], [2], [3]])
y = np.array([4, 5, 6])
b = np.broadcast(x, y)
out = np.empty(b.shape)
out.flat = [u+v for (u,v) in b]
print(out)
print('内置broadcast:\n',x+y)
print('--------broadcast_to--------')
x = np.array([1, 2, 3])
print(np.broadcast_to(x, (3, 3)))
print('--------broadcast_arrays--------')
x = np.array([[1,2,3]])
y = np.array([[4],[5]])
print(np.broadcast_arrays(x, y))
print('-------expand_dims---------')
x = np.array(([1,2],[3,4]))
print('x:\n', x)
print('x.shape:', x.shape)
y = np.expand_dims(x, axis=0)
print('y:\n', y)
print('y.shape:', y.shape)
z = np.expand_dims(x, axis=(0,2))
print('z:\n', z)
print('z.shape:\n',z.shape)
print('-------squeeze---------')
x = np.array([[[0], [1], [2]]])
print('x.shape:', x.shape)
print('np.squeeze(x).shape:', np.squeeze(x).shape)
print('np.squeeze(x, axis=0).shape:', np.squeeze(x, axis=0).shape)
print('-------atleast_1d()atleast_2d()atleast_3d()---------')
x = np.arange(6).reshape(1,6)
print('x:\n', x)
print('np.atleast_1d(1):\n',np.atleast_1d(1))
print('np.atleast_2d(x):\n',np.atleast_2d(x))
print('np.atleast_3d(x):\n',np.atleast_3d(x))
结果:
8.4 组合数组
方法 | 描述 | 参数含义 |
---|---|---|
numpy.concatenate((a1,a2,…), axis=0, out=None, dtype=None, casting=“same_kind”) | 沿现有轴连接一系列数组。 | casting:{‘no’, ‘equiv’, ‘safe’, ‘same_kind’, ‘unsafe’}; |
numpy.stack(arrays, axis=0, out=None, *, dtype=None, casting=“same_kind”) | 沿新轴连接一系列数组。 | axis:整数 要滚动的轴。其他轴的位置相对于彼此不发生变化; |
numpy.hstack(tup) | 水平(按列)顺序堆叠数组。 | tup:值为序列,除了可以是任何长度的1-D阵列之外,阵列沿着除第二轴以外的所有轴必须具有相同的形状。 |
numpy.vstack(tup) | 垂直(行)按顺序堆叠数组。 | |
numpy.dstack(tup) | 沿深度方向(沿第三轴)按顺序堆叠数组。 | |
numpy.column_stack(tup) | 将一维数组作为列堆叠到二维数组中。 | |
numpy.block(arrays) | 从块的嵌套列表中组装一个nd数组。 |
测试:
print('-------concatenate---------')
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
print('np.concatenate((a, b), axis=0):\n', np.concatenate((a, b), axis=0))
print('np.concatenate((a, b.T), axis=1):\n', np.concatenate((a, b.T), axis=1))
print('np.concatenate((a, b), axis=None):\n', np.concatenate((a, b), axis=None))
print('-------stack---------')
arrays = [np.random.randn(3, 4) for _ in range(10)]
print('np.stack(arrays, axis=0).shape:\n', np.stack(arrays, axis=0).shape)
print('np.stack(arrays, axis=1).shape:\n', np.stack(arrays, axis=1).shape)
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print('np.stack((a, b)):\n', np.stack((a, b)))
print('np.stack((a, b), axis=-1):\n', np.stack((a, b), axis=-1))
print('-------hstack---------')
a = np.array((1,2,3))
b = np.array((4,5,6))
print('a.shape:', a.shape)
print('np.hstack((a,b)):\n', np.hstack((a,b)))
a = np.array([[1],[2],[3]])
b = np.array([[4],[5],[6]])
print('a.shape:', a.shape)
print('np.hstack((a,b)):\n', np.hstack((a,b)))
print('-------vstack---------')
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print('a.shape:', a.shape)
print('np.vstack((a,b)):\n', np.vstack((a,b)))
a = np.array([[1], [2], [3]])
b = np.array([[4], [5], [6]])
print('a.shape:', a.shape)
print('np.vstack((a,b)):\n', np.vstack((a,b)))
print('-------dstack---------')
a = np.array((1,2,3))
b = np.array((4,5,6))
print('a.shape:', a.shape)
print('np.dstack((a,b)):\n', np.dstack((a,b)))
a = np.array([[1],[2],[3]])
b = np.array([[4],[5],[6]])
print('a.shape:', a.shape)
print('np.dstack((a,b)):\n', np.dstack((a,b)))
print('-------column_stack---------')
a = np.array((1,2,3))
b = np.array((4,5,6))
print('a.shape:', a.shape)
print('np.column_stack((a,b)):\n', np.column_stack((a,b)))
print('-------block---------')
A = np.eye(2) * 2
B = np.eye(3) * 3
np.block([
[A, np.zeros((2, 3))],
[np.ones((3, 2)), B ]
])
结果:
8.5 拆分数组
方法 | 描述 | 参数含义 |
---|---|---|
numpy.split(arr, indices_or_sections, axis) | 将数组拆分为多个子数组,作为arr的视图。 | indices_or_sections:int or 1-D array,如果indices _or_sections是整数N,则该数组将沿轴划分为N个相等的数组。如果无法进行这样的拆分,则会引发错误。 如果indices _or_sections是排序整数的一维数组,则条目指示数组沿轴的拆分位置。 |
numpy.hsplit(ary, indices_or_sections) | 将一个数组拆分为多个子数组。 | |
numpy.vsplit(ary, indices_or_sections) | 将一个数组拆分为多个子数组。 | |
numpy.dsplit(ary, indices_or_sections) | 将一个数组拆分为多个子数组。 | |
numpy.array_split() | 垂直(行)将数组拆分为多个子数组。 |
测试:
print('-------split---------')
x = np.arange(9.0)
print('np.split(x, 3):\n', np.split(x, 3))
print('np.split(x, 3):\n', np.split(x, [3, 5, 6, 10]))
print('-------hsplit---------')
x = np.arange(16.0).reshape(4, 4)
print('x:\n', x)
print('np.hsplit(x, np.array([0,2, 3,4])):\n', np.hsplit(x, np.array([0,2, 3,4])))
print('np.hsplit(x, 2):\n', np.hsplit(x, 2))
print('-------vsplit---------')
print('np.vsplit(x, np.array([0,2, 3,4])):\n', np.vsplit(x, np.array([0,2, 3,4])))
print('np.vsplit(x, 2):\n', np.vsplit(x, 2))
print('-------dsplit---------')
x = np.arange(16.0).reshape(2, 2, 4)
print('x:\n', x)
print('np.dsplit(x, np.array([0,2, 3,4])):\n', np.dsplit(x, np.array([0,2, 3,4])))
print('np.dsplit(x, 2):\n', np.dsplit(x, 2))
print('-------array_split---------')
x = np.arange(8.0)
print('np.array_split(x, 3):\n', np.array_split(x, 3))
结果:
8.6 添加和删除元素
方法 | 描述 | 参数含义 |
---|---|---|
numpy.delete(arr, obj, axis=None) | 返回一个新的数组,该数组具有沿删除的轴的子数组。 | obj:指示要沿指定轴移除的子数组的索引; |
numpy.insert(arr, obj,values, axis=None) | 沿给定轴在给定索引之前插入值。 | values:要插入到arr中的值。如果值的类型与arr的类型不同,则将值转换为arr类型。 |
numpy.append(arr, obj, axis=None) | 将值附加到数组的末尾。 | |
numpy.resize(arr, new_shape) | 返回具有指定形状的新数组。 | |
numpy.trim_zeros(filt, trim=‘fb’) | 修剪一维数组或序列中的前导和/或尾随零。 | trim:一个字符串,“f”表示从前面修剪,“b”表示从后面修剪。默认值为“fb”,从数组的前面和后面修剪零。 |
numpy.unique(arr,return_index=False, return_inverse=False, return_counts=False, axis=None, *, equal_nan=True) | 查找数组的唯一元素。 | (详情至官方文档) |
测试:
print('-------delete---------')
arr = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
print('arr:\n', arr)
print('np.delete(arr, 1, 0):\n', np.delete(arr, 1, 0))
print('np.delete(arr, np.s_[::2], 1):\n', np.delete(arr, np.s_[::2], 1))
print('np.delete(arr, [1,3,5], None):\n', np.delete(arr, [1,3,5], None))
print('-------insert---------')
a = np.array([[1, 1], [2, 2], [3, 3]])
print('a:\n', a)
print('np.insert(a, 1, 5):\n', np.insert(a, 1, 5))
print('np.insert(a, [2,4], [5, 6]):\n', np.insert(a, [2,4], [5, 6]))
print('np.insert(a, 1, 5, axis=1):\n', np.insert(a, 1, 5, axis=1))
print('np.insert(a, [1], [[6],[6],[6]], axis=1):\n', np.insert(a, [1], [[6],[6],[6]], axis=1))
print('-------append---------')
print('np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]]):\n', np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]]))
print('np.append([[1, 2, 3], [4, 5, 6]], [[7, 8, 9]], axis=0):\n', np.append([[1, 2, 3], [4, 5, 6]], [[7, 8, 9]], axis=0))
print('-------resize---------')
a=np.array([[0,1],[2,3]])
print('np.resize(a,(2,5)):\n', np.resize(a,(2,5)))
print('-------trim_zeros---------')
a = np.array((0, 0, 0, 1, 2, 3, 0, 2, 1, 0))
print('a:\n', a)
print('np.trim_zeros(a):\n', np.trim_zeros(a))
print('np.trim_zeros(a, ''f''):\n', np.trim_zeros(a, 'f'))
print('np.trim_zeros(a, ''b''):\n', np.trim_zeros(a, 'b'))
结果:
9、常用函数
9.1 字符串
方法 | 描述 | 参数含义 |
---|---|---|
numpy.char.add(arr1, arr2) | 返回两个str或unicode数组的按元素的字符串连接。 | |
numpy.char.multiply(a1, a2) | 返回(a * i),即按元素方式的字符串多重连接。 | |
numpy.char.center(a, width, fillchar=’ ') | 返回的拷贝一与在长度的字符串居中其元素宽度。 | |
numpy.char.capitalize(a) | 将字符串第一个字母转换为大写 | |
numpy.char.title(a) | 将字符串的每个单词的第一个字母转换为大写 | |
numpy.char.lower(a) | 返回一个将元素转换为小写的数组。 | |
numpy.char.upper(a) | 返回一个数组,其中元素转换为大写。 | |
numpy.char.split(a, sep=None, maxsplit=None) | 在每个元件一个,返回的词的列表字符串中,使用月作为分隔符串。 | |
numpy.char.splitlines(a, keepends=None) | 返回元素中的行列表,以换行符分割 | |
numpy.char.strip(a, chars=None) | 在每个元件一个,其中移除了前缘和后字符返回副本。 | |
numpy.char.join(sep, seq) | 返回一个字符串,该字符串是序列seq中字符串的串联。 | |
numpy.char.replace(a, old, new, count=None) | 对于每一个元素一个,返回字符串的副本串中出现的所有旧的换成新的。 | |
numpy.char.decode(a, encoding=None, errors=None) | 按元素调用str.decode。 | |
numpy.char.encode(a, encoding=None, errors=None) | 逐元素调用str.encode。 |
测试:
print('---------add----------')
print (np.char.add(['hello'],[' xyz']))
print (np.char.add(['hello', 'hi'],[' abc', ' xyz']))
print('---------multiply----------')
a = np.array(['a', 'b', 'c'])
i = np.array([1, 2, 3])
print('np.char.multiply(x, 3):\n', np.char.multiply(a, 3))
print('np.char.multiply(a, i):\n', np.char.multiply(a, i))
print('---------center----------')
c = np.array(['a1b2','1b2a','b2a1','2a1b'])
print('c:\n', c)
print('np.char.center(c, width=9, fillchar=''*''):\n', np.char.center(c, width=9, fillchar='*'))
print('---------capitalize----------')
print('np.char.capitalize(c):\n', np.char.capitalize(c))
print('---------title----------')
c = np.array(['ab2','1b2a','b2a1','2a1b'])
print('c:\n', c)
print('np.char.title(c):\n', np.char.title(c))
print('---------lower----------')
c = np.array(['A1B C', '1BCA', 'BCA1'])
print('c:\n', c)
print('np.char.lower(c):\n', np.char.lower(c))
print('---------upper----------')
c = np.array(['a1b c', '1bca', 'bca1'])
print('c:\n', c)
print('np.char.upper(c):\n', np.char.upper(c))
print('---------split----------')
print ('np.char.split (''i like runoob?''):\n', np.char.split ('i like runoob?'))
print ('np.char.split (''www.runoob.com'', sep = ''.''):\n', np.char.split ('www.runoob.com', sep = '.'))
print('---------splitlines----------')
print ('np.char.splitlines(''i\\nlike runoob?'')\n', np.char.splitlines('i\nlike runoob?'))
print('---------strip----------')
c = np.array(['aAaAaA', ' aA ', 'abBABba'])
print('c:\n', c)
print('np.char.strip(c, ''a''):\n', np.char.strip(c, 'a'))
print('---------join----------')
print('np.char.join([''-'', ''.''], [''ghc'', ''osd'']):\n', np.char.join(['-', '.'], ['ghc', 'osd']))
print('---------replace----------')
a = np.array(['That is a mango', 'Monkeys eat mangos'])
print('a:\n', a)
print('np.char.replace(a, ''mango'', ''banana''):\n', np.char.replace(a, 'mango', 'banana'))
print('---------encode----------')
a = np.char.encode('runoob', 'cp500')
print('np.char.encode(''runoob'', ''cp500'')\n',np.char.encode('runoob', 'cp500') )
print('---------decode----------')
print('np.char.decode(a, ''cp500'')\n',np.char.decode(a, 'cp500') )
结果:
9.2 数学
测试:
a = np.array([0,30,45,60,90])
print('np.sin(a*np.pi/180):\n', np.sin(a*np.pi/180))
print('np.cos(a*np.pi/180):\n', np.cos(a*np.pi/180))
print('np.tan(a*np.pi/180):\n', np.tan(a*np.pi/180))
print('np.around(a, decimals = 1):\n', np.around(a, decimals = 1))
print('np.around(a, decimals = -1):\n', np.around(a, decimals = -1))
print('np.floor(a):\n', np.floor(a))
print('np.ceil(a):\n', np.ceil(a))
结果:
9.3 算术
测试:
#维度相同 或者 符合广播原则
a = np.arange(9, dtype = np.float_).reshape(3,3)
b = np.array([10,10,10])
print('a:\n', a)
print('b:\n', b)
print('np.add(a,b):\n', np.add(a,b))
print('np.subtract(a,b):\n', np.subtract(a,b))
print('np.multiply(a,b):\n', np.multiply(a,b))
print('np.divide(a,b):\n', np.divide(a,b))
print('np.reciprocal(a):\n', np.reciprocal(a))
print('np.power(a,b):\n', np.power(a,b))
print('np.mod(a,b):\n', np.mod(a,b))
print('np.remainder(a,b):\n', np.remainder(a,b))
结果:
9.4 统计
测试:
a = np.array([[3,7,5],[8,4,3],[2,4,9]])
b = np.array([[10, 7, 4], [3, 2, 1]])
print('a:\n', a)
print('np.amin(a,1):\n', np.amin(a,1)) #一行行取最小值,返回list
print('np.amin(a,0):\n', np.amin(a,0)) #一列列取最小值,返回list
print('np.ptp(a, axis = 1):\n', np.ptp(a, axis = 1)) #行极差
print('np.ptp(a, axis = 0):\n', np.ptp(a, axis = 0)) #列极差
print('np.percentile(a, 50,axis=1):\n', np.percentile(a, 50, axis=1)) #从小到大行排名第50%那个数 %0是最小的
print('np.percentile(a, 50,axis=0):\n', np.percentile(a, 50, axis=0)) #从小到大列排名第50%那个数
print('np.median(a, axis = 1):\n', np.median(a, axis = 1)) #每行中位数
print('np.median(a, axis = 0):\n', np.median(a, axis = 0)) #每列中位数
print('np.mean(a, axis = 1):\n', np.mean(a, axis = 1))#算数平均数
print('np.mean(a, axis = 0):\n', np.mean(a, axis = 0))#算数平均数
print('np.average(a,weights = [], axis = 0):\n', np.average(a,axis = 0)) #加权平均数,3
print('np.std([1,2,3,4]):\n', np.std([1,2,3,4])) #标准差
print('np.var([1,2,3,4]):\n', np.var([1,2,3,4])) #方差
结果:
9.5 排序、条件筛选
测试:
print('----------sort----------')
a = np.array([[3,7],[9,1]])
print('a:\n', a)
print ('np.sort(a):\n', np.sort(a))
print ('np.sort(a, axis=0):\n', np.sort(a, axis=0))
dt = np.dtype([('name', 'S10'),('age', int)])
a = np.array([("raju",21),("anil",25),("ravi", 17), ("amar",27)], dtype = dt)
print('a:\n', a)
print ('np.sort(a, order = ''name''):\n',np.sort(a, order = 'name'))
print('----------argsort----------')
x = np.array([3, 1, 2])
print('x:\n', x)
print ('np.argsort(x):\n', np.argsort(x))
print('----------lexsort----------')
nm = ('raju','anil','ravi','amar')
dv = ('f.y.', 's.y.', 's.y.', 'f.y.')
ind = np.lexsort((dv,nm))#优先照顾靠后的列
print ('[nm[i] + ", " + dv[i] for i in ind]:\n',[nm[i] + ", " + dv[i] for i in ind])
print('----------sort_complex----------')
print('np.sort_complex([1 + 2j, 2 - 1j, 3 - 2j, 3 - 3j, 3 + 5j]):\n', np.sort_complex([1 + 2j, 2 - 1j, 3 - 2j, 3 - 3j, 3 + 5j]))
print('----------sort----------')
a = np.array([3, 4, 2, 1])
print ('np.partition(a, 3):\n',np.partition(a, 3))
print ('np.partition(a, (1,3)):\n',np.partition(a, (1,3)))
print('----------nonzero----------')
a = np.array([0,4,5,6])
print('a:\n', a)
print ('np.nonzero (a):\n',np.nonzero (a))
print('----------where----------')
x = np.arange(9.).reshape(3, 3)
print('x:\n',x)
print('x[np.where(x > 3)]:\n',x[np.where(x > 3)])
print('----------extract----------')
condition = np.mod(x,2) == 0
print ('condition:\n',condition)
print ('使用条件提取元素:')
print ('np.extract(condition, x):\n',np.extract(condition, x))
结果:
9.6 试图、浅拷贝、深拷贝
副本是一个数据的完整的拷贝,如果我们对副本进行修改,它不会影响到原始数据,物理内存不在同一位置。
视图是数据的一个别称或引用,通过该别称或引用亦便可访问、操作原有数据,但原有数据不会产生拷贝。如果我们对视图进行修改,它会影响到原始数据,物理内存在同一位置。
视图一般发生在:
- 1、numpy 的切片操作返回原数据的视图。
- 2、调用 ndarray 的 view() 函数产生一个视图。
副本一般发生在:
- Python 序列的切片操作,调用deepCopy()函数。
- 调用 ndarray 的 copy() 函数产生一个副本。
测试:
print('--------view()(浅拷贝)-------')
a = np.arange(6).reshape(3,2)
b = a.view()
print('a:\n',a)
print ('a 的 id():',id(a))
print ('a.view() 的 id():',id(b))
print('-------numpy的切片创建视图--------')
arr = np.arange(12)
print('arr:\n',arr)
a=arr[3:]#使用切片创建视图修改数据会影响到原始数组
print('id(arr[3:])',id(arr[3:]),'\nid(a):',id(a))
print('-------numpy.copy创建副本(深拷贝)--------')
a = np.array([[10,10], [2,3], [4,5]])
b = a.copy()
print('id(a):',id(a),'\nid(a.copy()):',id(a.copy()))
结果:
10、矩阵
方法 | 描述 | 参数含义 |
---|---|---|
numpy.matlib.empty(shape, dtype=None, order=‘C’) | 返回给定形状和类型的新矩阵,而无需初始化条目。 | |
numpy.matlib.zeros(shape, dtype=None, order=‘C’) | 返回给定形状和类型的矩阵,并用零填充。 | |
numpy.matlib.ones(shape, dtype=None, order=‘C’) | 一个矩阵。 | |
numpy.matlib.eye(n, M=None, k=0, dtype=<class ‘float’>, order=‘C’) | 返回一个矩阵,在对角线上有一个,在其他地方为零。 | |
numpy.matlib.identity(n, dtype=None) | 返回给定大小的平方单位矩阵。 | |
numpy.matlib.repmat(arr, m, n) | 重复从0D到2D数组或矩阵MxN次。 | |
numpy.matlib.rand(*args) | 返回具有给定形状的随机值矩阵。 | |
numpy.matlib.randn(*args) | 返回一个随机矩阵,其中包含来自“标准正态”分布的数据。 |
测试:
print('----------numpy.matlib.empty--------------')
print(np.matlib.empty((2,2), dtype=int))
print('----------numpy.matlib.zeros--------------')
print(np.matlib.zeros((3, 3)))
print('----------numpy.matlib.ones--------------')
print(np.matlib.ones((3, 3)))
print('----------numpy.matlib.eye--------------')
print(np.matlib.eye(3, k=1, dtype=float))
print('----------numpy.matlib.identity--------------')
print(np.matlib.identity(3, dtype=int))
print('----------numpy.matlib.repmat--------------')
a2 = np.asmatrix(np.arange(6).reshape(2, 3))
print(np.matlib.repmat(a2, 2, 3))
print('----------numpy.matlib.rand--------------')
print(np.matlib.rand((2, 3)))
print('----------numpy.matlib.randn--------------')
print(2.5 * np.matlib.randn((2, 4)) + 3)
结果: