第三章:NumPy (2)
NumPy(2) 简介
数组与元素操作
数值迭代
NumPy
迭代器对象numpy.nditer
提供了一种灵活访问一个或者多个数组元素的方式。
import numpy as np
# 使用 arange() 函数创建一个 2X3 数组,并使用 nditer 对它进行迭代
a = np.arange(6).reshape(2, 3)
print("原始数组是:")
print(a)
print()
print("迭代输出元素:")
for x in np.nditer(a):
print(x, end=" ")
运行结果
原始数组是: [[0 1 2] [3 4 5]]
迭代输出元素: 0 1 2 3 4 5
import numpy as np
a = np.arange(0, 60, 10)
a = a.reshape(2, 3)
print("原始数组是:")
print(a)
print()
for x in np.nditer(a, op_flags=["readwrite"]):
x[...] = 3 * x
print("修改后的数组是:")
print(a)
运行结果
原始数组是: [[ 0 10 20] [30 40 50]]
修改后的数组是: [[ 0 30 60] [ 90 120 150]]
- 如果两个数组是可广播的,
nditer
组合对象能够同时迭代它们。
import numpy as np
# 假设数组 a 的维度为 3X4,数组 b 的维度为 1X4 ,则使用以下迭代器(数组 b 被广播到 a 的大小)
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("第二个数组为:")
print(b)
print()
print("修改后的数组为:")
for x, y in np.nditer([a, b]):
print("%d:%d" % (x, y), end=", ")
运行结果
第一个数组为: [[ 0 5 10 15] [20 25 30 35] [40 45 50 55]]
第二个数组为: [1 2 3 4]
修改后的数组为: 0:1, 5:2, 10:3, 15:4, 20:1, 25:2, 30:3, 35:4, 40:1, 45:2, 50:3, 55:4,
数组变形
- 修改数组形状
函数 | 描述 |
---|---|
reshape | 不改变数据的条件下修改形状 |
flat | 数组元素迭代器 |
flatten | 返回一份数组拷贝,对拷贝所做的修改不会影响原始数组 |
ravel | 返回展开数组 |
numpy.reshape
- 不改变数据的条件下修改形状
numpy.reshape(arr, newshape, order='C')
参数 | 描述 |
---|---|
arr | 要修改形状的数组 |
newshape | 整数或者整数数组,新的形状应当兼容原有形状 |
order | 'C' -- 按行,'F' -- 按列,'A' -- 原顺序,'k' -- 元素在内存中的出现顺序 |
import numpy as np
a = np.arange(8)
print("原始数组:")
print(a)
print("\n")
b = a.reshape(4, 2)
print("修改后的数组:")
print(b)
运行结果
原始数组: [0 1 2 3 4 5 6 7]
修改后的数组: [[0 1] [2 3] [4 5] [6 7]]
numpy.ndarray.flat
- 数组元素迭代器
import numpy as np
a = np.arange(9).reshape(3, 3)
print("原始数组:")
for row in a:
print(row)
# 对数组中每个元素都进行处理,可以使用flat属性,该属性是一个数组元素迭代器:
print("迭代后的数组:")
for element in a.flat:
print(element)
运行结果
始数组: [0 1 2] [3 4 5] [6 7 8] 迭代后的数组: 0 1 2 3 4 5 6 7 8
import numpy as np
a = np.arange(100).reshape(20, 5)
print(a.flat[5])
运行结果
5
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)
print("\n")
# 默认按行
print("展开的数组:")
print(a.flatten())
print("\n")
print("以 F 风格顺序展开的数组:")
print(a.flatten(order="F"))
运行结果
原数组: [[0 1 2 3] [4 5 6 7]]
展开的数组: [0 1 2 3 4 5 6 7]
以 F 风格顺序展开的数组: [0 4 1 5 2 6 3 7]
numpy.ravel
- 返回展开数组
numpy.ravel(a, order='C')
参数 | 描述 |
---|---|
order | 'C' -- 按行,'F' -- 按列,'A' -- 原顺序,'K' -- 元素在内存中的出现顺序 |
import numpy as np
a = np.arange(8).reshape(2, 4)
print("原数组:")
print(a)
print()
print("调用 ravel 函数之后:")
print(a.ravel())
print()
print("以 F 风格顺序调用 ravel 函数之后:")
print(a.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 | 对换数组的维度 |
ndarray.T | 和 self.transpose() 相同 |
rollaxis | 向后滚动指定的轴 |
swapaxes | 对换数组的两个轴 |
transpose
- 对换数组的维度
numpy.transpose(arr, axes)
参数 | 描述 |
---|---|
arr | 要操作的数组 |
axes | 整数列表,对应维度,通常所有维度都会对换 |
import numpy as np
a = np.arange(12).reshape(3, 4)
print("原数组:")
print(a)
print()
print("对换数组:")
print(np.transpose(a))
运行结果
原数组: [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]]
对换数组: [[ 0 4 8] [ 1 5 9] [ 2 6 10] [ 3 7 11]]
import numpy as np
a = np.arange(10).reshape(2, 5)
print("原数组:")
print(a)
print("\n")
print("对换数组:")
print(np.transpose(a))
运行结果
原数组: [[0 1 2 3 4] [5 6 7 8 9]]
对换数组: [[0 5] [1 6] [2 7] [3 8] [4 9]]
ndarray.T
- 和
self.transpose()
相同
import numpy as np
a = np.arange(20).reshape(4, 5)
print("原数组:")
print(a)
print("\n")
print("转置数组:")
print(a.T)
运行结果
原数组: [[ 0 1 2 3 4] [ 5 6 7 8 9] [10 11 12 13 14] [15 16 17 18 19]]
转置数组: [[ 0 5 10 15] [ 1 6 11 16] [ 2 7 12 17] [ 3 8 13 18] [ 4 9 14 19]]
rollaxis
`rollaxis`
- 向后滚动指定的轴
numpy.rollaxis(arr, axis, start)
参数 | 描述 |
---|---|
arr | 要操作的数组 |
axis | 要向后滚动的轴,其它轴的相对位置不会改变 |
start | 默认为零,表示完整的滚动。会滚动到特定位置 |
import numpy as np
a = np.arange(8).reshape(2, 2, 2)
print("原数组:")
print(a)
print("翻转后:")
# 将轴2放到轴0之前(1, 2, 0)
print(np.rollaxis(a, 2))
print("翻转后:")
# 将轴2放到轴1之前(0, 2, 1)
print(np.rollaxis(a, 2, 1))
运行结果
原数组: [[[0 1] [2 3]]
[[4 5] [6 7]]] 翻转后: [[[0 2] [4 6]]
[[1 3] [5 7]]] 翻转后: [[[0 2] [1 3]]
[[4 6] [5 7]]]
import numpy as np
a = np.arange(9).reshape(3, 3)
print(np.rollaxis(a, 1))
运行结果
[[0 3 6] [1 4 7] [2 5 8]]
swapaxes
`rollaxis`
- 对换数组的两个轴
numpy.swapaxes(arr, axis1, axis2)
参数 | 描述 |
---|---|
arr | 要操作的数组 |
axis1 | 对应第一个轴的整数 |
axis2 | 对应第二个轴的整数 |
import numpy as np
a = np.arange(8).reshape(2, 2, 2)
print("原数组:")
print(a)
print("\n")
print("调用 swapaxes 函数后的数组:")
# 交换轴2和轴0
print(np.swapaxes(a, 2, 0))
print("\n")
print("调用 swapaxes 函数后的数组:")
# 交换轴1和轴0
print(np.swapaxes(a, 1, 0))
运行结果
原数组: [[[0 1] [2 3]]
[[4 5] [6 7]]]
调用 swapaxes 函数后的数组: [[[0 4] [2 6]]
[[1 5] [3 7]]]
调用 swapaxes 函数后的数组:
[[[0 1] [4 5]]
[[2 3] [6 7]]]
修改维度
概览
维度 | 描述 |
---|---|
broadcast | 产生模仿广播的对象 |
broadcast_to | 将数组广播到新形状 |
expand_dims | 扩展数组的形状 |
squeeze | 从数组的形状中删除一维条目 |
numpy.broadcast
- 产生模仿广播的对象
numpy.broadcast_to
- 将数组广播到新形状
# 输入数组,新的形状,默认false【为true返回子类,否则返回基类】
numpy.broadcast_to(array, shape, subok)
import numpy as np
a = np.arange(4).reshape(1, 4)
print("原数组:")
print(a)
print("\n")
print("调用 broadcast_to 函数之后:")
print(np.broadcast_to(a, (4, 4)))
运行结果
原数组: [[0 1 2 3]]
调用 broadcast_to 函数之后: [[0 1 2 3] [0 1 2 3] [0 1 2 3] [0 1 2 3]]
numpy.expand_dims
- 扩展数组的形状
numpy.expand_dims(arr, axis)
参数 | 描述 |
---|---|
arr | 要操作的数组 |
axis | 新轴插入的位置 |
numpy.squeeze
- 从数组的形状中删除一维条目
numpy.squeeze(arr, axis)
参数 | 描述 |
---|---|
arr | 要操作的数组 |
axis | 整数或整数元组,用于选择形状中一维条目的子集 |
数组连接
概览
函数 | 描述 |
---|---|
concatenate | 连接沿现有轴的数组序列 |
stack | 沿着新的轴加入一系列数组 |
hstack | 水平堆叠序列中的数组(列方向) |
vstack | 竖直堆叠序列中的数组(行方向) |
numpy.concatenate
- 连接沿现有轴的数组序列
numpy.concatenate((a1, a2, ...), axis)
参数 | 描述 |
---|---|
a1, a2, ... | 相同类型的数组 |
axis | 沿着它连接数组的轴,默认为 0 |
import numpy as np
a = np.array([[1, 2], [3, 4]])
print("第一个数组:")
print(a)
print("\n")
b = np.array([[5, 6], [7, 8]])
print("第二个数组:")
print(b)
print("\n")
# 两个数组的维度相同
print("沿轴 0 连接两个数组:")
print(np.concatenate((a, b)))
print("\n")
print("沿轴 1 连接两个数组:")
print(np.concatenate((a, b), axis=1))
运行结果
第一个数组: [[1 2] [3 4]]
第二个数组: [[5 6] [7 8]]
沿轴 0 连接两个数组: [[1 2] [3 4] [5 6] [7 8]]
沿轴 1 连接两个数组: [[1 2 5 6] [3 4 7 8]]
numpy.stack
- 沿着新的轴加入一系列数组
numpy.stack(arrays, axis)
参数 | 描述 |
---|---|
arrays | 相同形状的数组序列 |
axis | 返回数组中的轴,输入数组沿着它来堆叠 |
numpy.hstack
- 水平堆叠序列中的数组(列方向)
numpy.vstack
- 竖直堆叠序列中的数组(行方向)
数组分割
概览
函数 | 数组及操作 |
---|---|
split | 将一个数组分割为多个子数组 |
hsplit | 将一个数组水平分割为多个子数组(按列) |
vsplit | 将一个数组垂直分割为多个子数组(按行) |
numpy.split
- 将一个数组分割为多个子数组
# 要分割的数组,分割点的位置或分割的块数,沿着哪个轴进行分割【默认为0】
split(ary, indices_or_sections, axis=0)
import numpy as np
a = np.arange(9)
print("第一个数组:")
print(a)
print("\n")
print("将数组分为三个大小相等的子数组:")
b = np.split(a, 3)
print(b)
print("\n")
print("将数组在一维数组中表明的位置分割:")
b = np.split(a, [4, 7])
print(b)
运行结果
第一个数组: [0 1 2 3 4 5 6 7 8]
将数组分为三个大小相等的子数组: [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]
将数组在一维数组中表明的位置分割: [array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8])]
numpy.hsplit
- 将一个数组水平分割为多个子数组(按列)
numpy.vsplit
- 将一个数组垂直分割为多个子数组(按行)
添加 / 删除元素
概览
函数 | 元素及描述 |
---|---|
resize | 返回指定形状的新数组 |
append | 将值添加到数组末尾 |
insert | 沿指定轴将值插入到指定下标之前 |
delete | 删掉某个轴的子数组,并返回删除后的新数组 |
unique | 查找数组内的唯一元素 |
numpy.resize
- 返回指定形状的新数组
numpy.resize(arr, shape)
参数 | 描述 |
---|---|
arr | 要修改大小的数组 |
shape | 返回数组的新形状 |
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
print("第一个数组:")
print(a)
print("\n")
print("第一个数组的形状:")
print(a.shape)
print("\n")
b = np.resize(a, (3, 2))
print("第二个数组:")
print(b)
print("\n")
print("第二个数组的形状:")
print(b.shape)
print("\n")
# 要注意 a 的第一行在 b 中重复出现,因为尺寸变大了
print("修改第二个数组的大小:")
b = np.resize(a, (3, 3))
print(b)
运行结果
第一个数组: [[1 2 3] [4 5 6]]
第一个数组的形状: (2, 3)
第二个数组: [[1 2] [3 4] [5 6]]
第二个数组的形状: (3, 2)
修改第二个数组的大小: [[1 2 3] [4 5 6] [1 2 3]]
import numpy as np
a = np.array([[1, 2, 3, 4], [4, 5, 6, 7]])
b = np.resize(a, (3, 4))
print(b)
运行结果
[[1 2 3 4] [4 5 6 7] [1 2 3 4]]
numpy.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("第一个数组:")
print(a)
print("\n")
print("向数组添加元素:")
print(np.append(a, [7, 8, 9]))
print("\n")
print("沿轴 0 添加元素:")
print(np.append(a, [[7, 8, 9]], axis=0))
print("\n")
print("沿轴 1 添加元素:")
print(np.append(a, [[5, 5, 5], [7, 8, 9]], axis=1))
运行结果
第一个数组: [[1 2 3] [4 5 6]]
向数组添加元素: [1 2 3 4 5 6 7 8 9]
沿轴 0 添加元素: [[1 2 3] [4 5 6] [7 8 9]]
沿轴 1 添加元素: [[1 2 3 5 5 5] [4 5 6 7 8 9]]
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("第一个数组:")
print(a)
print("\n")
print("未传递 Axis 参数。 在删除之前输入数组会被展开。")
print(np.insert(a, 3, [11, 12]))
print("\n")
print("传递了 Axis 参数。 会广播值数组来配输入数组。")
print("沿轴 0 广播:")
print(np.insert(a, 1, [11], axis=0))
print("\n")
print("沿轴 1 广播:")
print(np.insert(a, 1, 11, axis=1))
运行结果
第一个数组: [[1 2] [3 4] [5 6]]
未传递 Axis 参数。 在删除之前输入数组会被展开。 [ 1 2 3 11 12 4 5 6]
传递了 Axis 参数。 会广播值数组来配输入数组。 沿轴 0 广播: [[ 1 2] [11 11] [ 3 4] [ 5 6]]
沿轴 1 广播: [[ 1 11 2] [ 3 11 4] [ 5 11 6]]
numpy.delete
- 删掉某个轴的子数组,并返回删除后的新数组
Numpy.delete(arr, obj, axis)
参数 | 描述 |
---|---|
arr | 输入数组 |
obj | 可以被切片,整数或者整数数组,表明要从输入数组删除的子数组 |
axis | 沿着它删除给定子数组的轴,如果未提供,则输入数组会被展开 |
import numpy as np
a = np.arange(12).reshape(3, 4)
print("第一个数组:")
print(a)
print("\n")
print("未传递 Axis 参数。 在插入之前输入数组会被展开。")
print(np.delete(a, 5))
print("\n")
print("删除第二列:")
print(np.delete(a, 1, axis=1))
print("\n")
print("包含从数组中删除的替代值的切片:")
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(np.delete(a, np.s_[::2]))
运行结果
第一个数组: [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]]
未传递 Axis 参数。 在插入之前输入数组会被展开。 [ 0 1 2 3 4 6 7 8 9 10 11]
删除第二列: [[ 0 2 3] [ 4 6 7] [ 8 10 11]]
包含从数组中删除的替代值的切片: [ 2 4 6 8 10]
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])
print("第一个数组:")
print(a)
print("\n")
print("第一个数组的去重值:")
u = np.unique(a)
print(u)
print("\n")
print("去重数组的索引数组:")
u, indices = np.unique(a, return_index=True)
print(indices)
print("\n")
print("我们可以看到每个和原数组下标对应的数值:")
print(a)
print("\n")
print("去重数组的下标:")
u, indices = np.unique(a, return_inverse=True)
print(u)
print("\n")
print("下标为:")
print(indices)
print("\n")
print("使用下标重构原数组:")
print(u[indices])
print("\n")
print("返回去重元素的重复数量:")
u, indices = np.unique(a, return_counts=True)
print(u)
print(indices)
运行结果
第一个数组: [5 2 6 2 7 5 6 8 2 9]
第一个数组的去重值: [2 5 6 7 8 9]
去重数组的索引数组: [1 0 2 4 7 9]
我们可以看到每个和原数组下标对应的数值: [5 2 6 2 7 5 6 8 2 9]
去重数组的下标: [2 5 6 7 8 9]
下标为: [1 0 2 0 3 1 2 4 0 5]
使用下标重构原数组: [5 2 6 2 7 5 6 8 2 9]
返回去重元素的重复数量: [2 5 6 7 8 9] [3 2 2 1 1 1]