NumPy 中包含了一些处理数组的常用方法,大致可分为以下几类:
-
数组变维操作
-
数组转置操作
-
修改数组维度操作
-
连接与分割数组操作
数组变维操作
函数名称 | 函数介绍 |
---|---|
reshape | 在不改变数组元素的条件下,修改数组的形状。 |
flat | 返回是一个迭代器,可以用 for 循环遍历其中的每一个元素。 |
flatten | 以一维数组的形式返回一份数组的副本,对副本的操作不会影响到原数组。类似于在python中的深度拷贝。 |
ravel | 返回一个连续的扁平数组(即展开的一维数组),与 flatten不同,它返回的是数组视图(修改视图会影响原数组)。 |
ndarray.flat()
numpy.ndarray.flat 返回一个数组迭代器
arr_data = np.arange(9).reshape(3, 3)
print("第一个print的输出结果为:\n",arr_data)
print("*"*30)
for data in arr_data:
print(data)
# 使用列表循环遍历的用法,遍历整个列表
print("*"*30)
# 使用flat属性:
print("使用flat遍历循环的效果:")
for i in arr_data.flat:
print(i, end=",")
代码的运行结果为:
第一个print的输出结果为:
[[0 1 2]
[3 4 5]
[6 7 8]]
******************************
[0 1 2]
[3 4 5]
[6 7 8]
******************************
使用flat遍历循环的效果:
0,1,2,3,4,5,6,7,8,
综上所述,nditer 可以用于同时迭代多个数组,并且可以控制迭代的顺序和步长,而 flat 只能按照一维的顺序迭代数组的每个元素。
-
nditer 和 flat 都是 numpy 中用于循环遍历数组的方法,但它们之间有一些区别。
-
nditer:nditer 是一个多维迭代器,可以用于同时迭代多个数组。它可以迭代不同形状的数组,并且可以控制迭代的顺序和步长。nditer 返回的是一个迭代器对象,可以使用 for 循环来遍历数组的每个元素。
-
flat:flat 是一个一维迭代器,可以用于按照 C 风格的顺序(即按行展开)迭代数组的每个元素。它返回的是一个迭代器对象,可以使用 for 循环来遍历数组的每个元素。
ndarray.flatten()
numpy.ndarray.flatten 返回一份数组副本,对副本修改不会影响原始数组
#有点类似于python中的deepcopy。
arr_num = np.arange(8).reshape(2, 4)
print(arr_num)
# 默认按行C风格展开的数组
print(arr_num.flatten())
# 以F风格顺序展开的数组
print("最后一个print的结果为:\n", arr_num.flatten(order='F'))
代码的运行结果为:
[[0 1 2 3]
[4 5 6 7]]
[0 1 2 3 4 5 6 7]
最后一个print的结果为:
[0 4 1 5 2 6 3 7]
numpy.ravel()
numpy.ravel() 将多维数组中的元素以一维数组的形式展开,该方法返回数组的视图(view),如果修改,则会影响原始数组。
arr_num = np.arange(8).reshape(2, 4)
print('原数组:')
print(arr_num)
print('调用 ravel 函数后:')
print(arr_num.ravel())
print('F 风格顺序调用 ravel 函数之后:')
print(arr_num.ravel(order='F'))
代码的运行结果为:
原数组:
[[0 1 2 3]
[4 5 6 7]]
调用 ravel 函数后:
[0 1 2 3 4 5 6 7]
F 风格顺序调用 ravel 函数之后:
[0 4 1 5 2 6 3 7]
数组转置操作
函数名称 | 说明 |
---|---|
transpose | 将数组的维度值进行对换,比如二维数组维度(2,4)使用该方法后为(4,2)。 |
ndarray.T | 与 transpose 方法相同。 |
rollaxis | 沿着指定的轴向后滚动至规定的位置。 |
swapaxes | 对数组的轴进行对换。 |
numpy.transpose()
numpy.transpose() 用于对换多维数组的维度,比如二维数组使用此方法可以实现矩阵转置
# 语法格式
numpy.transpose(arr, axes)
-
arr:要操作的数组
-
axes:可选参数,元组或者整数列表,将会按照该参数进行转置。
arr_num = np.arange(12).reshape(3, 4)
print(arr_num)
# 将三行四列转化为四行三列
print(np.transpose(arr_num))
print("原矩阵和转置过后的矩阵相乘结果为:", arr_num * np.transpose(arr_num))
代码的运行结果为:
Traceback (most recent call last):
File "D:\pythonProjet\pythonclass\Numpy\numpy数组的操作.py", line 40, in <module>
print("原矩阵和转置过后的矩阵相乘结果为:", arr_num * np.transpose(arr_num))
ValueError: operands could not be broadcast together with shapes (3,4) (4,3)
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[ 0 4 8]
[ 1 5 9]
[ 2 6 10]
[ 3 7 11]]
这里如果按照矩阵的乘法,应该是可以直接相乘的,但是这里报错了,报错的原因是说两个数组的广播机制不同,不能直接相乘,为什么会报这个错,鼠鼠我啊也不知道为什么,如果大家对这个东西了解的话,可以私聊我哦。
numpy.rollaxis()
该方法表示沿着指定的轴,向后滚动至一个特定位置
# 语法格式
numpy.rollaxis(arr, axis, start)
# 将数组arr所对应的axis轴 放在 start轴的前面,start轴往后移一"列"
-
arr:要传入的数组;
-
axis:沿着哪条轴向后滚动,其它轴的相对位置不会改变;
-
start:默认以 0 轴开始,可以根据数组维度调整它的值。
arr_one = np.arange(8).reshape(2, 2, 2)
print("第一个print的输出结果为:\n", arr_one)
arr_two = np.rollaxis(arr_one, 2)
print("第二个print的输出结果为:\n", arr_two)
arr_three = np.rollaxis(arr_one, 2, 1)
print("第三个print的输出结果为:\n", arr_three)
代码的运行结果:
第一个print的输出结果为:
[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
第二个print的输出结果为:
[[[0 2]
[4 6]]
[[1 3]
[5 7]]]
第三个print的输出结果为:
[[[0 2]
[1 3]]
[[4 6]
[5 7]]]
大家要怎么去理解这个函数方法呢,其实大家画一个表格就可以啦!鼠鼠给大家演示一下。这里鼠鼠想偷个懒,就举六个例子吧,我们默认开始为z轴,而且,大家要如何去看数组呢,这里整体分开,我们可以把他看成为0,1,然后分别看行为x轴,看列位y轴。
数组元素 | z轴 | x轴 | y轴 |
0 | 0 | 0 | 0 |
1 | 0 | 0 | 1 |
2 | 0 | 1 | 0 |
3 | 0 | 1 | 1 |
4 | 1 | 0 | 0 |
5 | 1 | 0 | 1 |
6 | 1 | 1 | 0 |
好,鼠鼠我已经把前面六个元素的坐标写出来了,我们看一下第二个运行结果,start是默认从0开始的,我们这里就把z轴当成0,x轴当成1,y轴当成2,其意思就是让我们把第2的轴放在0前面,那这个时候,2的坐标就变成了0,0,1了,然后我们再去把坐标放回数组中,2就到了我们第二个print输出结果的位置上了。
数组元素 | z轴 | x轴 | y轴 |
0 | 0 | 0 | 0 |
1 | 1 | 0 | 0 |
2 | 0 | 0 | 1 |
3 | 1 | 0 | 1 |
4 | 0 | 1 | 0 |
5 | 1 | 1 | 0 |
6 | 0 | 1 | 1 |
这就是使用了新的函数后的位置坐标。
numpy.swapaxes()
-
该方法用于交换数组的两个轴
arr_one = np.arange(8).reshape(2, 2, 2)
print(arr_one)
arr_two = np.swapaxes(arr_one, 2, 1)
print(arr_two)
代码的运行结果为:
[[[0 1]
[2 3]]
[[4 5]
[6 7]]]
[[[0 2]
[1 3]]
[[4 6]
[5 7]]]
这里的代码运行结果为什么是这样,鼠鼠我在这里就不多解释了,转换的原理和上面的函数原理一样,如果没有看懂的友友们,可以再回去看看哦。
修改数组维度
函数名称 | 描述说明 |
---|---|
broadcast | 生成一个模拟广播的对象。 |
broadcast_to | 将数组广播为新的形状。 |
expand_dims | 扩展数组的形状。 |
squeeze | 从数组的形状中删除一维项。 |
numpy.broadcast()
-
用于模仿广播的对象,它返回一个对象,该对象封装了将一个数组广播到另一个数组的结果。
-
该函数使用两个数组作为输入参数
arr_one = np.array([[1], [2], [3]])
arr_two = np.array([4, 5, 6])
# 对arr_two广播arr_one
new_arr = np.broadcast(arr_one, arr_two)
print("第一个print的结果为:\n", new_arr)
# new_arr拥有iterator属性
new_arr_one, new_arr_two = new_arr.iters
print(next(new_arr_one), next(new_arr_two))
print(next(new_arr_one), next(new_arr_two))
# 使用broadcast将a与b相加
arr_obj = np.broadcast(arr_one, arr_two)
f = np.empty(arr_obj.shape)
print("第一个f的输出结果:", f)
f.flat = [x + y for (x, y) in arr_obj]
print(f)
print("arr_one + arr_two的结果为:\n", arr_one + arr_two)
代码的运行结果为:
第一个print的结果为:
<numpy.broadcast object at 0x00000204AF6D5250>
1 4
1 5
第一个f的输出结果: [[0.00000000e+000 0.00000000e+000 0.00000000e+000]
[0.00000000e+000 0.00000000e+000 1.58101007e-321]
[2.54130561e+151 1.44008035e+214 2.00460015e-313]]
[[5. 6. 7.]
[6. 7. 8.]
[7. 8. 9.]]
arr_one + arr_two的结果为:
[[5 6 7]
[6 7 8]
[7 8 9]]
numpy.broadcast_to()
该函数将数组广播到新形状中,它在原始数组的基础上返回一个只读视图。 如果新形状不符合 NumPy 的广播规则,则会抛出 ValueError 异常
什么是广播规则呢,这里的广播规则只要两个数组的行数相同,这里两个数组就可以广播到相同的数组类型,然后直接相加减。
arr_one = np.arange(4).reshape(1, 4)
print("原数组", arr_one)
print(np.broadcast_to(arr_one, (4, 4)))
代码运行的结果为:
原数组 [[0 1 2 3]]
[[0 1 2 3]
[0 1 2 3]
[0 1 2 3]
[0 1 2 3]]
这里的arr_one数组,我们通过numpy的广播规则,广播到了一个4行4列的数组形式。
numpy.expand_dims()
在指定位置插入新的轴,从而扩展数组的维度
这里的在指定的位置插入新的轴的方法,和结果的原理,鼠鼠这里已经在上方的表格中讲解过了,所以大家如果还是没有看懂的话,可以往上面再看看。
arr_one = np.array(([1, 2], [3, 4]))
print('数组 arr_one:', arr_one)
# 在1轴处插入新的轴
arr_two = np.expand_dims(arr_one, axis=1)
print('数组 arr_two:', arr_two)
print('数组 x 和 y 的形状:', arr_one.shape, arr_two.shape)
print(arr_two.ndim)
代码的运行结果为:
arr_one = np.array(([1, 2], [3, 4]))
print('数组 arr_one:\n', arr_one)
# 在1轴处插入新的轴
arr_two = np.expand_dims(arr_one, axis=1)
print('数组 arr_two:\n', arr_two)
print('数组 x 和 y 的形状:\n', arr_one.shape, arr_two.shape)
print(arr_two.ndim)
numpy.squeeze()
从给定数组的形状中删除一维的条目
这里有注意的地方就是,这里删除的条目,一定是一维的数据,如果一个行数之间有两行,这里使用这个方法就是报错。
arr_one = np.arange(9).reshape(1, 3, 3)
print(arr_one)
arr_two = np.squeeze(arr_one)
print(arr_two)
print('数组 arr_one 和 arr_two 的形状:')
print(arr_one.shape, arr_two.shape)
代码的运行结果为:
[[[0 1 2]
[3 4 5]
[6 7 8]]]
[[0 1 2]
[3 4 5]
[6 7 8]]
数组 arr_one 和 arr_two 的形状:
(1, 3, 3) (3, 3)
连接与分割
连接与分割数组是数组的两种操作方式
-
连接数组的方式
函数名称 | 描述说明 |
---|---|
concatenate | 沿指定轴连接两个或者多个相同形状的数组 |
hstack | 按水平顺序堆叠序列中数组(列方向) |
vstack | 按垂直方向堆叠序列中数组(行方向) |
-
分割数组的方式
函数名称 | 描述说明 |
---|---|
split | 将一个数组分割为多个子数组 |
hsplit | 将一个数组水平分割为多个子数组(按列) |
vsplit | 将一个数组垂直分割为多个子数组(按行) |
连接数组操作
numpy.concatenate((a1, a2, ...), axis)
# a1, a2, ...:表示一系列相同类型的数组;
# axis:沿着该参数指定的轴连接数组,默认为 0。
实例说明:创建两个 a 、b 数组,并沿指定轴将它们连接起来。注意两个数组的形状要保持一致。
# 创建数组arr_one
arr_one = np.array([[10, 20], [30, 40]])
print("1.\n", arr_one)
# 创建数组arr_two
arr_two = np.array([[50, 60], [70, 80]])
print("2.\n", arr_two)
# 沿轴 0 连接两个数组
print("3.\n", np.concatenate((arr_one, arr_two))) # 等同于vstack
# 沿轴 1 连接两个数组
print("4.\n", np.concatenate((arr_one, arr_two), axis=1)) # 等同于hstack
代码的运行结果为:
1.
[[10 20]
[30 40]]
2.
[[50 60]
[70 80]]
3.
[[10 20]
[30 40]
[50 60]
[70 80]]
4.
[[10 20 50 60]
[30 40 70 80]]
分割数组操作
numpy.split() 沿指定的轴将数组分割为多个子数组
numpy.split(ary, num, axis)
# ary:被分割的数组
# num:若是一个整数,代表用该整数平均切分,若是一个数组,则代表沿轴切分的位置(左开右闭);
# axis:默认为0,表示横向切分;为1时表示纵向切分。
arr_one = np.arange(8)
# 原数组
print("1.\n", arr_one)
# 将数组分为两个形状大小相等的子数组
arr_two = np.split(arr_one, 2)
print("1.\n", arr_two)
# 将数组在一维数组中标明要位置分割
arr_two = np.split(arr_one, [3, 5])
print("1.\n", arr_two)
代码运行的结果为:
1.
[0 1 2 3 4 5 6 7]
1.
[array([0, 1, 2, 3]), array([4, 5, 6, 7])]
1.
[array([0, 1, 2]), array([3, 4]), array([5, 6, 7])]