NumPy-数组迭代和操作
NumPy-迭代数组
迭代方法
-
ndarray 也可以通过for 循环来实现迭代。
- 当维数多于一维时,迭代操作使用嵌套的for循环。
- 迭代时,通常按照第一条轴(默认为行)对二维数组进行扫描。如果需要按其他维度迭代,可以使用apply_along_axis(func,axis,arr)函数指定当前轴。
-
NumPy还包含一个循环迭代器类numpy.nditer
-
生成的迭代器(Iterator)对象是一个根据位置进行遍历的对象
import numpy as np a = np.arange(6).reshape(2,3) print ('原始数组是:') print (a) print ('\n') print ('迭代输出元素:') for x in np.nditer(a): print (x, end=", " ) print ('\n') # 输出 原始数组是: [[0 1 2] [3 4 5]] 迭代输出元素: 0, 1, 2, 3, 4, 5,
-
迭代的顺序与数组的内容布局相匹配,不受数据排序的影响。
import numpy as np a = np.arange(6).reshape(2,3) for x in np.nditer(a.T): print (x, end=", " ) print ('\n') for x in np.nditer(a.T.copy(order='C')): print (x, end=", " ) print ('\n') # a 和 a.T 的遍历顺序是一样的,也就是他们在内存中的存储顺序也是一样的 # a.T.copy(order = 'C') 的遍历结果是不同的,那是因为它的存储方式不同,默认是按行访问。 # 输出 0, 1, 2, 3, 4, 5, 0, 3, 1, 4, 2, 5,
-
控制迭代顺序
-
控制遍历顺序
- for x in np.nditer(a, order=‘F’):Fortran order,即是列序优先;
- for x in np.nditer(a.T, order=‘C’):C order,即是行序优先;
import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('原始数组是:') print (a) print ('\n') # 输出 原始数组是: [[ 0 5 10 15] [20 25 30 35] [40 45 50 55]] print ('原始数组的转置是:') b = a.T print (b) # 输出 原始数组的转置是: [[ 0 20 40] [ 5 25 45] [10 30 50] [15 35 55]] print ('以 C 风格顺序排序:') c = b.copy(order='C') print (c) for x in np.nditer(c): print (x, end=", " ) # 输出 以 C 风格顺序排序: [[ 0 20 40] [ 5 25 45] [10 30 50] [15 35 55]] 0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55, print ('以 F 风格顺序排序:') c = b.copy(order='F') print (c) for x in np.nditer(c): print (x, end=", " ) # 输出 以 F 风格顺序排序: [[ 0 20 40] [ 5 25 45] [10 30 50] [15 35 55]] 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55
-
如果需要特定的顺序,可以设置显式参数,来强制 nditer 对象使用某种顺序
import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('原始数组是:') print (a) # 输出 原始数组是: [[ 0 5 10 15] [20 25 30 35] [40 45 50 55]] print ('以 C 风格顺序排序:') for x in np.nditer(a, order = 'C'): print (x, end=", " ) # 输出 以 C 风格顺序排序: 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, print ('以 F 风格顺序排序:') for x in np.nditer(a, order = 'F'): print (x, end=", " ) # 输出 以 F 风格顺序排序: 0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55,
修改数组中元素的值
-
nditer 对象有另一个可选参数 op_flags。
- 默认情况下,nditer 将视待迭代遍历的数组为只读对象(read-only),为了在遍历数组的同时,实现对数组元素值的修改,必须指定 readwrite 或者 writeonly 的模式。
-
例子
import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('原始数组是:') print (a) # 输出 原始数组是: [[ 0 5 10 15] [20 25 30 35] [40 45 50 55]] for x in np.nditer(a, op_flags=['readwrite']): x[...]=2*x print ('修改后的数组是:') print (a) # 输出 修改后的数组是: [[ 0 10 20 30] [ 40 50 60 70] [ 80 90 100 110]]
使用外部循环
-
nditer 类的构造器拥有 flags 参数,它可以接受下列值:
参数 描述 c_index 可以跟踪 C 顺序的索引 f_index 可以跟踪 Fortran 顺序的索引 multi_index 每次迭代可以跟踪一种索引类型 external_loop 给出的值是具有多个值的一维数组,而不是零维数组 -
例子
import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print ('原始数组是:') print (a) # 输出 原始数组是: [[ 0 5 10 15] [20 25 30 35] [40 45 50 55]] print ('修改后的数组是:') for x in np.nditer(a, flags = ['external_loop'], order = 'F'): print (x, end=", " ) # 输出 修改后的数组是: [ 0 20 40], [ 5 25 45], [10 30 50], [15 35 55],
广播迭代
-
如果两个数组是可广播的,nditer 组合对象能够同时迭代它们。
-
假设数组 a 的维度为 3X4,数组 b 的维度为 1X4 ,则使用以下迭代器(数组 b 被广播到 a 的大小)
import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) b = np.array([1, 2, 3, 4], dtype = int) print ('修改后的数组为:') for x,y in np.nditer([a,b]): print ("%d:%d" % (x,y), end=", " ) # 输出 修改后的数组为: 0:1, 5:2, 10:3, 15:4, 20:1, 25:2, 30:3, 35:4, 40:1, 45:2, 50:3, 55:4,
NumPy-数组操作
修改数组形状
-
修改数组形状的函数
函数 描述 reshape 不改变数据的条件下修改形状 flat 数组元素迭代器 flatten 返回一份数组拷贝,对拷贝所做的修改不会影响原始数组 ravel 返回展开数组
numpy.reshape
-
numpy.reshape 函数可以在不改变数据的条件下修改形状
-
函数格式
numpy.reshape(arr, newshape, order='C')
-
参数介绍
参数 描述 arr 要修改形状的数组 newshape 整数或者整数数组,新的形状应当兼容原有形状 order ‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘k’ – 元素在内存中的出现顺序。 -
例子
import numpy as np a = np.arange(8) b = a.reshape(4,2) print (b) # 输出 [[0 1] [2 3] [4 5] [6 7]]
numpy.ndarray.flat
-
numpy.ndarray.flat 是一个数组元素迭代器
import numpy as np a = np.arange(9).reshape(3,3) for row in a: print (row) # 输出 [0 1 2] [3 4 5] [6 7 8] #对数组中每个元素都进行处理,可以使用 flat 属性,该属性是一个数组元素迭代器: print ('迭代后的数组:') for element in a.flat: print (element) # 输出 0 1 2 3 4 5 6 7 8
numpy.ndarray.flatten
-
numpy.ndarray.flatten 返回一份数组拷贝,对拷贝所做的修改不会影响原始数组
-
函数格式
ndarray.flatten(order='C')
-
参数说明
- order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘K’ – 元素在内存中的出现顺序。
-
例子
import numpy as np a = np.arange(8).reshape(2,4) print ('展开的数组:') print (a.flatten()) print ('\n') # 输出 展开的数组: [0 1 2 3 4 5 6 7] print ('以 F 风格顺序展开的数组:') print (a.flatten(order = 'F')) # 输出 以 F 风格顺序展开的数组: [0 4 1 5 2 6 3 7]
numpy.ravel
-
numpy.ravel() 展平的数组元素,顺序通常是"C风格",返回的是数组视图(view,有点类似 C/C++引用reference的意味),修改会影响原始数组。
-
函数格式
numpy.ravel(a, order='C')
-
参数说明
- order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘K’ – 元素在内存中的出现顺序。
-
例子
import numpy as np a = np.arange(8).reshape(2,4) print ('调用 ravel 函数之后:') print (a.ravel()) # 输出 调用 ravel 函数之后: [0 1 2 3 4 5 6 7] print ('以 F 风格顺序调用 ravel 函数之后:') print (a.ravel(order = 'F')) # 输出 以 F 风格顺序调用 ravel 函数之后: [0 4 1 5 2 6 3 7]
翻转数组
-
翻转数组函数
函数 描述 transpose 对换数组的维度 ndarray.T 和 self.transpose() 相同 rollaxis 向后滚动指定的轴 swapaxes 对换数组的两个轴
numpy.transpose
-
numpy.transpose 函数用于对换数组的维度
-
函数格式
numpy.transpose(arr, axes)
-
参数说明
参数 说明 arr 要操作的数组 axes 整数列表,对应维度,通常所有维度都会对换。 -
例子
import numpy as np a = np.arange(12).reshape(3,4) print ('对换数组:') print (np.transpose(a)) # 输出 对换数组: [[ 0 4 8] [ 1 5 9] [ 2 6 10] [ 3 7 11]]
numpy.ndarray.T
-
numpy.ndarray.T 类似 numpy.transpose:
-
例子
import numpy as np a = np.arange(12).reshape(3,4) print ('转置数组:') print (a.T) # 输出 转置数组: [[ 0 4 8] [ 1 5 9] [ 2 6 10] [ 3 7 11]]
numpy.rollaxis
-
numpy.rollaxis 函数向后滚动特定的轴到一个特定位置
-
函数格式
numpy.rollaxis(arr, axis, start)
-
参数说明
参数 说明 arr 数组 axis 要向后滚动的轴,其它轴的相对位置不会改变 start 默认为零,表示完整的滚动。会滚动到特定位置。 -
例子
import numpy as np # 创建了三维的 ndarray a = np.arange(8).reshape(2,2,2) print ('原数组:') print (a) print ('获取数组中一个值:') print(np.where(a==6)) print(a[1,1,0]) # 为 6 print ('\n') # 将轴 2 滚动到轴 0(宽度到深度) print ('调用 rollaxis 函数:') b = np.rollaxis(a,2,0) print (b) # 查看元素 a[1,1,0],即 6 的坐标,变成 [0, 1, 1] # 最后一个 0 移动到最前面 print(np.where(b==6)) print ('\n') # 将轴 2 滚动到轴 1:(宽度到高度) print ('调用 rollaxis 函数:') c = np.rollaxis(a,2,1) print (c) # 查看元素 a[1,1,0],即 6 的坐标,变成 [1, 0, 1] # 最后的 0 和 它前面的 1 对换位置 print(np.where(c==6)) print ('\n')
numpy.swapaxes
-
numpy.swapaxes 函数用于交换数组的两个轴
-
函数格式
numpy.swapaxes(arr, axis1, axis2)
-
参数介绍
参数 描述 arr 数组 axis1 对应第一个轴的整数 axis2 对应第二个轴的整数 -
例子
import numpy as np # 创建了三维的 ndarray a = np.arange(8).reshape(2,2,2) # 现在交换轴 0(深度方向)到轴 2(宽度方向) print ('调用 swapaxes 函数后的数组:') print (np.swapaxes(a, 2, 0)) #元素 a[i,j,k] 变成 a[k,j,i]
修改数组维度
维度 | 描述 |
---|---|
broadcast | 产生模仿广播的对象 |
broadcast_to | 将数组广播到新形状 |
expand_dims | 扩展数组的形状 |
squeeze | 从数组的形状中删除一维条目 |
numpy.broadcast
-
numpy.broadcast 用于模仿广播的对象,它返回一个对象,该对象封装了将一个数组广播到另一个数组的结果。
-
函数格式
res = numpy.broadcast(arr1,arr2)
-
参数介绍
参数 说明 res 对象封装了将一个数组广播到另一个数组的结果 arr1 源数组 arr2 目标数组 -
例子
import numpy as np x = np.array([[1], [2], [3]]) y = np.array([4, 5, 6]) # 对 y 广播 x b = np.broadcast(x,y) # 它拥有 iterator 属性,基于自身组件的迭代器元组 print ('对 y 广播 x:') r,c = b.iters # Python3.x 为 next(context) ,Python2.x 为 context.next() print (next(r), next(c)) print (next(r), next(c)) # 输出 1 4 1 5 # shape 属性返回广播对象的形状 print (b.shape) # 输出 (3, 3) # 手动使用 broadcast 将 x 与 y 相加 b = np.broadcast(x,y) c = np.empty(b.shape) print (c.shape) # 输出 (3, 3) #调用 flat 函数 c.flat = [u + v for (u,v) in b] print (c) # 输出 [[5. 6. 7.] [6. 7. 8.] [7. 8. 9.]] # 获得了和 NumPy 内建的广播支持相同的结果 print ('x 与 y 的和:') print (x + y) # 输出 [[5 6 7 ] [6 7 8 ] [7 8 9 ]]
numpy.broadcast_to
-
numpy.broadcast_to 函数将数组广播到新形状。它在原始数组上返回只读视图。 它通常不连续。 如果新形状不符合 NumPy 的广播规则,该函数可能会抛出ValueError。
-
函数格式
numpy.broadcast_to(array, shape, subok)
-
参数介绍
参数 描述 array 输入数组 shape 新形状 subok 可选参数 -
例子
import numpy as np a = np.arange(4).reshape(1,4) print (np.broadcast_to(a,(4,4))) # 输出 [[0 1 2 3] [0 1 2 3] [0 1 2 3] [0 1 2 3]]
numpy.expand_dims
-
numpy.expand_dims 函数通过在指定位置插入新的轴来扩展数组形状
-
函数格式
numpy.expand_dims(arr, axis)
-
参数说明
参数 描述 arr 输入数组 axis 新轴插入的位置 -
例子
import numpy as np x = np.array(([1,2],[3,4])) y = np.expand_dims(x, axis = 0) print (y) # 输出 [[[1 2] [3 4]]] print (x.shape, y.shape) # 输出 (2, 2) (1, 2, 2) # 在位置 1 插入轴 y = np.expand_dims(x, axis = 1) print (y) # 输出 [[[1 2]] [[3 4]]] print (x.ndim,y.ndim) # 输出 2 3 print (x.shape, y.shape) # 输出 (2, 2) (2, 1, 2)
numpy.squeeze
-
numpy.squeeze 函数从给定数组的形状中删除一维的条目
-
函数格式
numpy.squeeze(arr, axis)
-
参数说明
参数 描述 arr 输入数组 axis 整数或整数元组,用于选择形状中一维条目的子集 -
例子
import numpy as np x = np.arange(9).reshape(1,3,3) y = np.squeeze(x) print (y) # 输出 [[0 1 2] [3 4 5] [6 7 8]] print (x.shape, y.shape) # 输出 (1, 3, 3) (3, 3)
连接数组
函数 | 描述 |
---|---|
concatenate | 连接沿现有轴的数组序列 |
stack | 沿着新的轴加入一系列数组。 |
hstack | 水平堆叠序列中的数组(列方向) |
vstack | 竖直堆叠序列中的数组(行方向) |
numpy.concatenate
-
numpy.concatenate 函数用于沿指定轴连接相同形状的两个或多个数组
-
函数格式
numpy.concatenate((a1, a2, ...), axis)
-
参数说明
参数 描述 a1, a2, … 相同类型的数组 axis 沿着它连接数组的轴,默认为 0 -
例子
import numpy as np a = np.array([[1,2],[3,4]]) b = np.array([[5,6],[7,8]]) print (np.concatenate((a,b))) # 输出 [[1 2] [3 4] [5 6] [7 8]] print (np.concatenate((a,b),axis = 1)) # 输出 [[1 2 5 6] [3 4 7 8]]
numpy.stack
-
numpy.stack 函数用于沿新轴连接数组序列
-
函数格式
numpy.stack(arrays, axis)
-
参数说明
参数 描述 arrays 相同形状的数组序列 axis 返回数组中的轴,输入数组沿着它来堆叠 -
例子
import numpy as np a = np.array([[1,2],[3,4]]) b = np.array([[5,6],[7,8]]) print (np.stack((a,b),0)) # 输出 [[[1 2] [3 4]] [[5 6] [7 8]]] print (np.stack((a,b),1)) # 输出 [[[1 2] [5 6]] [[3 4] [7 8]]]
numpy.hstack
-
numpy.hstack 是 numpy.stack 函数的变体,它通过水平堆叠来生成数组。
-
例子
import numpy as np a = np.array([[1,2],[3,4]]) b = np.array([[5,6],[7,8]]) c = np.hstack((a,b)) print (c) # 输出 [[1 2 5 6] [3 4 7 8]]
numpy.vstack
-
numpy.vstack 是 numpy.stack 函数的变体,它通过垂直堆叠来生成数组。
-
例子
import numpy as np a = np.array([[1,2],[3,4]]) b = np.array([[5,6],[7,8]]) c = np.vstack((a,b)) print (c) # 输出 [[1 2] [3 4] [5 6] [7 8]]
分割数组
函数 | 数组及操作 |
---|---|
split | 将一个数组分割为多个子数组 |
hsplit | 将一个数组水平分割为多个子数组(按列) |
vsplit | 将一个数组垂直分割为多个子数组(按行) |
numpy.split
-
numpy.split 函数沿特定的轴将数组分割为子数组
-
函数格式
numpy.split(ary, indices_or_sections, axis)
-
参数说明
参数 描述 ary 被分割的数组 indices_or_sections 如果是一个整数,就用该数平均切分
如果是一个数组,为沿轴切分的位置(左开右闭)axis 设置沿着哪个方向进行切分,默认为 0,横向切分,即水平方向。
为 1 时,纵向切分,即竖直方向。 -
例子
import numpy as np a = np.arange(9) b = np.split(a,3) print (b) # 输出 [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])] b = np.split(a,[4,7]) print (b) # 输出 [array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8])] a = np.arange(16).reshape(4, 4) b = np.split(a,2) print(b) # 输出 [array([[ 0, 1, 2, 3], [4, 5, 6, 7]]), array([[ 8, 9, 10, 11],[12, 13, 14, 15]])] c = np.split(a,2,1) print(c) # 输出 [array([[ 0, 1], [ 4, 5], [ 8, 9], [12, 13]]), array([[ 2, 3], [ 6, 7], [10, 11], [14, 15]])]
numpy.hsplit
-
numpy.hsplit 函数用于水平分割数组,通过指定要返回的相同形状的数组数量来拆分原数组。
-
例子
import numpy as np harr = np.arange(12).reshape(2, 6) print(harr) # 输出 [[0, 1, 2, 3, 4, 5 ] [6, 7, 8, 9, 10, 11]] print(np.hsplit(harr, 3)) # 输出 [array([[0, 1],[6, 7]]), array([[2, 3],[8, 9]]), array([[4, 5],[10, 11]])]
numpy.vsplit
-
numpy.vsplit 沿着垂直轴分割,其分割方式与hsplit用法相同。
-
例子
import numpy as np a = np.arange(16).reshape(4,4) b = np.vsplit(a,2) print (b) # 输出 [array([[0, 1, 2, 3], [4, 5, 6, 7]]), array([[8, 9, 10, 11],[12, 13, 14, 15]])]
数组元素的添加与删除
函数 | 元素及描述 |
---|---|
resize | 返回指定形状的新数组 |
append | 将值添加到数组末尾 |
insert | 沿指定轴将值插入到指定下标之前 |
delete | 删掉某个轴的子数组,并返回删除后的新数组 |
unique | 查找数组内的唯一元素 |
numpy.resize
-
numpy.resize 函数返回指定大小的新数组。如果新数组大小大于原始大小,则包含原始数组中的元素的副本。
-
函数格式
numpy.resize(arr, shape)
-
参数说明
参数 说明 arr 要修改大小的数组 shape 返回数组的新形状 -
例子
import numpy as np a = np.array([[1,2,3],[4,5,6]]) print (a.shape) # 输出 (2, 3) b = np.resize(a, (3,2)) print (b) # 输出 [[1 2] [3 4] [5 6]] b = np.resize(a,(3,3)) print (b) # 输出 [[1 2 3] [4 5 6] [1 2 3]] # a 的第一行在 b 中重复出现,因为尺寸变大了
numpy.append
-
numpy.append 函数在数组的末尾添加值。
- 追加操作会分配整个数组,并把原来的数组复制到新数组中。
- 此外,输入数组的维度必须匹配否则将生成ValueError。
-
append 函数返回的始终是一个一维数组。
-
函数格式
numpy.append(arr, values, axis=None)
-
参数说明
参数 描述 arr 输入数组 values 要向arr添加的值,需要和arr形状相同(除了要添加的轴) axis 默认为 None。当axis无定义时,是横向加成,返回总是为一维数组
当axis有定义的时候,分别为0和1的时候。
当axis有定义的时候,分别为0和1的时候(列数要相同)。
当axis为1时,数组是加在右边(行数要相同)。 -
例子
import numpy as np a = np.array([[1,2,3],[4,5,6]]) print (np.append(a, [7,8,9])) # 输出 [1 2 3 4 5 6 7 8 9] print (np.append(a, [[7,8,9]],axis = 0)) # 输出 [[1 2 3] [4 5 6] [7 8 9]] print (np.append(a, [[5,5,5],[7,8,9]],axis = 1)) # 输出 [[1 2 3 5 5 5] [4 5 6 7 8 9]]
numpy.insert
-
numpy.insert 函数在给定索引之前,沿给定轴在输入数组中插入值。
- 如果值的类型转换为要插入,则它与输入数组不同。
- 插入没有原地的,函数会返回一个新数组。
- 如果未提供轴,则输入数组会被展开。
-
函数格式
numpy.insert(arr, obj, values, axis)
-
参数说明
参数 描述 arr 输入数组 obj 在其之前插入值的索引 values 要插入的值 axis 沿着它插入的轴,如果未提供,则输入数组会被展开 -
例子
import numpy as np a = np.array([[1,2],[3,4],[5,6]]) print (np.insert(a,3,[11,12])) # 输出 [ 1 2 3 11 12 4 5 6] print (np.insert(a,1,[11],axis = 0)) # 输出 [[ 1 2] [11 11] [ 3 4] [ 5 6]] print (np.insert(a,1,11,axis = 1)) # 输出 [[ 1 11 2] [ 3 11 4] [ 5 11 6]]
numpy.delete
-
numpy.delete 函数返回从输入数组中删除指定子数组的新数组。
- 与 insert() 函数的情况一样,如果未提供轴参数,则输入数组将展开
-
函数格式
numpy.delete(arr, obj, axis)
-
参数说明
参数 描述 arr 输入数组 obj 可以被切片,整数或者整数数组,表明要从输入数组删除的子数组 axis 沿着它删除给定子数组的轴,如果未提供,则输入数组会被展开 -
例子
import numpy as np a = np.arange(12).reshape(3,4) print (np.delete(a,5)) # 输出 [ 0 1 2 3 4 6 7 8 9 10 11] print (np.delete(a,1,axis = 1)) # 输出 [[ 0 2 3] [ 4 6 7] [ 8 10 11]] a = np.array([1,2,3,4,5,6,7,8,9,10]) print (np.delete(a, np.s_[::2])) # 输出 [ 2 4 6 8 10]
numpy.unique
-
numpy.unique 函数用于去除数组中的重复元素。
-
函数格式
numpy.unique(arr, return_index, return_inverse, return_counts)
-
参数说明
参数 描述 arr 输入数组,如果不是一维数组则会展开 return_index 如果为 true
,返回新列表元素在旧列表中的位置(下标),并以列表形式储return_inverse 如果为 true
,返回旧列表元素在新列表中的位置(下标),并以列表形式储return_counts 如果为 true
,返回去重数组中的元素在原数组中的出现次数 -
例子
import numpy as np a = np.array([5,2,6,2,7,5,6,8,2,9]) u = np.unique(a) print (u) # 输出数组的去重值 [2 5 6 7 8 9] u,indices = np.unique(a, return_index = True) print (indices) # 输出去重数组的索引数组 [1 0 2 4 7 9] u,indices = np.unique(a,return_inverse = True) print (u) # 输出去重数组的下标 [2 5 6 7 8 9] print (indices) # 输出下标 [1 0 2 0 3 1 2 4 0 5] print (u[indices]) # 输出使用下标重构的原数组 [5 2 6 2 7 5 6 8 2 9] u,indices = np.unique(a,return_counts = True) print (u) print (indices) # 返回去重元素的重复数量: [2 5 6 7 8 9] [3 2 2 1 1 1]