文章目录
1. 概览
NumPy
提供了一系列的数组操作函数或方法,包括形状调整、元素增删、合并拆分、数学运算等,是数据科学、机器学习和科学计算中处理数值数据的核心工具。
基本操作:
函数/方法 | 描述 |
---|---|
copyto(dst, src) | 将值从源数组复制到目标数组(必要时广播)。 |
ndim(a) | 返回数组的维度数。 |
shape(a) | 返回数组的形状。 |
size(a[, axis]) | 返回沿指定轴的数组元素数量。 |
改变数组形状:
函数/方法 | 描述 |
---|---|
reshape(a, newshape) | 重塑数组形状(不复制数据,生成视图)。 |
ravel(a) | 返回连续的扁平化数组(视图)。 |
ndarray.flat | 数组的一维迭代器(属性)。 |
ndarray.flatten() | 返回展平为一维的数组副本。 |
转置及类似操作:
函数/方法 | 描述 |
---|---|
moveaxis(a, source, destination) | 将数组的指定轴移动到目标位置,调整维度顺序。 |
rollaxis(a, axis[, start]) | 将指定轴向后滚动到给定位置(默认到0轴前)。 |
swapaxes(a, axis1, axis2) | 直接互换数组中两个轴的位置。 |
ndarray.T | 返回数组的转置视图(交换行和列)。 |
transpose(a[, axes]) | 按指定顺序(axes 参数)重新排列数组的轴。 |
permute_dims(a[, axes]) | 按指定顺序重新排列轴(功能类似 transpose )。 |
matrix_transpose(x) | 转置矩阵或矩阵堆栈(等价于 x.swapaxes(-2, -1) )。 |
改变维度数量:
函数/方法 | 描述 |
---|---|
atleast_1d(*arys) | 将输入转换为至少一维的数组。 |
atleast_2d(*arys) | 将输入视为至少二维的数组。 |
atleast_3d(*arys) | 将输入视为至少三维的数组。 |
broadcast_to(array, shape) | 将数组广播到新形状。 |
broadcast_arrays(*args) | 将多个数组相互广播到相同形状。 |
expand_dims(a, axis) | 在指定轴位置扩展数组维度(增加一维)。 |
squeeze(a) | 移除数组中长度为1的轴。 |
数组类型转换:
函数/方法 | 描述 |
---|---|
asarray(a) | 将输入转换为数组(默认不复制数据)。 |
asanyarray(a) | 将输入转换为 ndarray ,但保留子类类型。 |
asmatrix(data) | 将输入解释为矩阵。 |
asfortranarray(a) | 返回内存中按 Fortran 顺序排列的数组(列优先)。 |
ascontiguousarray(a) | 返回内存中按 C 顺序排列的连续数组(行优先)。 |
asarray_chkfinite(a) | 将输入转换为数组,并检查 NaN 或无穷值。 |
require(a) | 返回满足特定内存或数据类型要求的数组。 |
合并数组:
函数/方法 | 描述 |
---|---|
concatenate(arrays, axis) | 沿现有轴连接数组序列。 |
stack(arrays) | 沿新轴堆叠数组序列(新增一个维度)。 |
block(arrays) | 从嵌套的块列表组装高维数组。 |
vstack(tup) | 垂直堆叠数组(按行方向)。 |
hstack(tup) | 水平堆叠数组(按列方向)。 |
dstack(tup) | 深度方向堆叠数组(沿第三轴)。 |
column_stack(tup) | 将一维数组按列堆叠为二维数组。 |
分割数组:
函数/方法 | 描述 |
---|---|
split(ary, indices) | 将数组均等分割为多个子数组(视图)。 |
array_split(ary, indices) | 分割数组(允许不均等分割)。 |
dsplit(ary, indices) | 沿第三轴(深度方向)分割数组。 |
hsplit(ary, indices) | 水平分割数组(按列方向)。 |
vsplit(ary, indices) | 垂直分割数组(按行方向)。 |
unstack(x, axis) | 沿指定轴将数组拆分为一系列子数组。 |
平铺数组:
函数/方法 | 描述 |
---|---|
tile(A, reps) | 通过重复数组构造新数组。 |
repeat(a, repeats) | 重复数组的每个元素。 |
增删元素:
函数/方法 | 描述 |
---|---|
delete(arr, obj) | 删除指定轴上的子数组。 |
insert(arr, obj, values) | 沿指定轴插入值。 |
append(arr, values) | 将值追加到数组末尾。 |
resize(a, new_shape) | 返回指定形状的新数组(自动填充或截断)。 |
trim_zeros(filt) | 移除沿某轴全为零的值。 |
unique(ar) | 返回数组的唯一元素。 |
pad(array, pad_width) | 对数组进行填充(如边缘补零)。 |
重新排列元素:
函数/方法 | 描述 |
---|---|
flip(m, axis) | 沿指定轴反转数组元素顺序。 |
fliplr(m) | 左右反转二维数组(沿轴1)。 |
flipud(m) | 上下反转二维数组(沿轴0)。 |
roll(a, shift) | 沿轴滚动数组元素(循环移位)。 |
rot90(m) | 将数组旋转90度(默认在轴0和1的平面)。 |
2. 基础操作
2.1 copyto
numpy.copyto()
:将源数组 src
的值复制到目标数组 dst
,必要时通过广播机制适配形状。
函数定义:
def copyto(dst, src, casting=None, where=None)
参数说明:
dst·:目标数组,必须已经存在,并且形状与广播后的
src` 兼容。- `src·:源数组,可以是数组或能被转换为数组的对象。
casting·:类型转换规则(默认 'same_kind'),控制
src到
dst` 的数据类型转换。where·:布尔掩码数组,指定哪些位置需要复制(
True` 表示复制,默认全部复制)。
注意事项:
dst
必须已存在且形状与广播后的src
兼容。- 直接修改
dst
的数据,无返回值。
示例 1 ,广播复制:
# 目标数组 (形状 3 x 3)
dst = np.zeros((3, 3), dtype=int)
src = np.array([1, 2, 3]) # 形状 (3,),广播到 (3, 3)
np.copyto(dst, src)
print(dst)
# [[1 2 3]
# [1 2 3]
# [1 2 3]]
示例 2 ,使用 casting
参数(类型转换)
dst = np.zeros(3, dtype=int)
src = np.array([1.5, 2.5, 3.5], dtype=float)
# 默认 'same_kind':允许 float → int(截断小数)
np.copyto(dst, src, casting='unsafe') # 必须显式允许不安全转换
print(dst) # [1 2 3]
# 若使用 casting='safe' 会报错(float到int被视为不安全)
# np.copyto(dst, src, casting='safe') # 抛出 TypeError
示例 3 ,使用 where
参数(条件复制)
dst = np.array([0, 0, 0, 0])
src = np.array([1, 2, 3, 4])
mask = np.array([True, False, True, False])
np.copyto(dst, src, where=mask)
print(dst) # [1 0 3 0]
2.2 ndim
numpy.ndim()
:返回数组的维度数(轴的数量),等效于属性 a.ndim
。
函数定义:
def ndim(a)
示例 :
a_scalar = np.array(5) # 标量(0维)
a_1d = np.array([1, 2, 3]) # 一维数组
a_2d = np.array([[1, 2], [3, 4]]) # 二维数组
print("维度数:", np.ndim(a_scalar)) # 0
print("维度数:", np.ndim(a_1d)) # 1
print("维度数:", np.ndim(a_2d)) # 2
2.3 shape
numpy.shape()
:返回数组的形状(各维度长度的元组),等效于属性 a.shape
。
函数定义:
def shape(a)
示例 :
a_1d = np.array([1, 2, 3]) # 形状 (3,)
a_2d = np.array([[1, 2], [3, 4]]) # 形状 (2, 2)
a_3d = np.arange(8).reshape(2, 2, 2) # 形状 (2, 2, 2)
print("形状:", np.shape(a_1d)) # (3,)
print("形状:", a_2d.shape) # (2, 2)
2.4 size
numpy.size()
:将数组在指定轴(axis
)上的元素数量。。
函数定义:
def size(a, axis=None)
参数说明:
a:输入数组(可以是列表、元组、
NumPy` 数组等)。axis
·:指定沿哪个轴计算元素数量。若未指定,返回数组总元素数。
示例:
b = np.arange(24).reshape(2, 3, 4) # 形状 (2, 3, 4)
print(np.size(b, 0)) # 输出: 2(轴0长度)
print(np.size(b, 1)) # 输出: 3(轴1长度)
print(np.size(b, 2)) # 输出: 4(轴2长度)
print(np.size(b)) # 输出: 24(总元素数)
3. 改变数组形状
在 NumPy
中数组的形状(shape
)描述了数组的维度结构,通过一个元组(tuple
)表示,元组中的每个元素对应数组在该维度上的长度,直观反映了数组的布局和元素排列方式。
无论在科学计算还是机器学习中,往往需要对数组的维度结构进行变换,方便计算或者满足某些函数的输入要求,比如从一维转为多维,或者将多维展平成一维向量, NumPy
提供了多种改变数组形状的函数或方法。
3.1 reshape
reshape()
(重塑):将数组的维度结构重新排列为指定形状,但不修改原始数据,是 NumPy
中用于改变数组形状的核心函数。
函数、方法定义:
# 函数
def reshape(a, /, shape=None, order='C', *, newshape=None, copy=None)
# 方法
def reshape(self, shape: None, /, *, order: _OrderACF = "C", copy: builtins.bool | None = None) -> Self: ...
参数说明:
a
:需要调整形状的数组。shape
:新形状,类型为int
或int
元组,必须与原形状兼容。order
:读取元素并填充新数组的索引顺序,可选:{‘C’, ‘F’, ‘A’}。copy
:是否复制数据,默认None
(仅在order
要求时复制)。newshape
:已被shape
参数取代,保留此参数仅用于向后兼容(2.1
版本标记为过时)。
示例 1 ,一维数组转换为二维数组:
# 一维数组
arr = np.arange(6) # [0, 1, 2, 3, 4, 5]
reshaped_arr = np.reshape(arr, [2, 3])
print(reshaped_arr)
# [[0 1 2]
# [3 4 5]]
# 也可以使用 `ndarray` 数组对象的 `reshape` 方法:
reshaped_arr = arr.reshape(2, 3) # 转换为 2 行 3 列
示例 2 ,二维数组转换为三维数组:
arr = np.arange(24).reshape(4, 6) # 4 行 6 列
new_arr = arr.reshape(2, 3, 4) # 2 层,每层 3 行 4 列
print(new_arr)
# [[[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
#
# [[12 13 14 15]
# [16 17 18 19]
# [20 21 22 23]]]
新数组和原数组之间的形状必须兼容,即总元素数相等,也就是形状各维度大小的乘积相等,例如上面的二维数组形状为 (4, 6)
总元素为 24
,三维数组 (2, 3, 4)
总元素为 24
,则形状兼容可以进行转换操作。
示例 3 ,形状不兼容时会报错 ValueError
:
arr = np.arange(24).reshape(4, 6) # 4 * 6 =24
new_arr = arr.reshape(2, 3, 5) # 2 * 3 * 5 = 25
# ValueError: cannot reshape array of size 24 into shape (2,3,5)
在执行形状变换时,会涉及到如何读取元素并填充新数组,由 order
参数控制:
C
:类C
索引顺序F
:类Fortran
索引顺序A
:若原数组内存是Fortran
连续的则按Fortran
顺序,否则按C
顺序
C
(C-like
)表示按行展开,优先填充行方向(横向扩展)的索引顺序,示例 4 ,一维数组转换为二维数组时,先填充第一行,再依次填充后面所有的行:
import numpy as np
# 一维数组
arr = np.arange(8)
print(arr) # [0 1 2 3 4 5 6 7]
# 二维数组
print("C:\n", arr.reshape((4, 2), order='C'))
# [[0 1]
# [2 3]
# [4 5]
# [6 7]]
F
(F-like
)按列展开,优先填充列方向(纵向扩展)的索引顺序,先填充第一列,再依次填充后面所有的列:
print("F:\n", arr.reshape((4, 2), order='F'))
# [[0 4]
# [1 5]
# [2 6]
# [3 7]]
reshape
操作中,可以让 NumPy
自动计算该维度的大小,并保持形状兼容,示例 5 ,只定义行数,自动推断列数:
# 一维数组
arr = np.arange(12) # [0, 1, 2, ..., 11]
reshaped = arr.reshape(3, -1) # 3 行,列数自动推断为 4
print("新形状:", reshaped.shape) # 输出 (3, 4)
3.2 ravel
ravel()
:将数组展平为连续的扁平化的一维数组。
函数、方法定义:
# 函数
def ravel(a, order='C')
# 方法
def ravel(self, /, order: _OrderKACF = "C") -> ndarray[tuple[int], _DType_co]: ...
参数说明:
a
:需要展平的多维数组,元素按照order
参数指定的顺序读取。order
:读取元素并填充新数组的索引顺序,可选:{'C','F', 'A', 'K'}
。
示例 1 ,将二维、三维数组展平(默认行优先):
arr = np.array([[1, 2, 3], [4, 5, 6]]) # 形状 (2, 3)
print(np.ravel(arr))
# 输出 [1 2 3 4 5 6]
arr = np.arange(24).reshape(2, 3, 4) # 形状 (2, 3, 4)
print(np.ravel(arr)) # [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
示例 2 ,对新数组的更改会影响原数组:
arr = np.array([[1, 2, 3], [4, 5, 6]]) # 形状 (2, 3)
print(arr) # 原始数组
# [[1 2 3]
# [4 5 6]]
new_arr = arr.ravel() # 对象调用
print(new_arr)
# [1 2 3 4 5 6]
# 修改新数组
new_arr[0] = 98
print(arr) # 原始数组
# 输出:
# [[98 2 3]
# [ 4 5 6]]
order
控制元素读取顺序:
C
行主序(C
风格):最后一个轴索引变化最快,第一个轴索引变化最慢。F
列主序(Fortran
风格):第一个轴索引变化最快,最后一个轴索引变化最慢。A
若数组内存是Fortran
连续的则按F
顺序,否则按C
顺序。K
按内存出现顺序读取(步长为负时反转数据)。
示例 3 ,优先按照列方向读取,先读取第一列,再依次读取后面所有的列:
arr = np.array([[1, 2, 3], [4, 5, 6]]) # 形状 (2, 3)
print(np.ravel(arr,"F"))
# [1 4 2 5 3 6]
arr = np.arange(24).reshape(2, 3, 4) # 形状 (2, 3, 4)
print(np.ravel(arr,"F"))
# [ 0 12 4 16 8 20 1 13 5 17 9 21 2 14 6 18 10 22 3 15 7 19 11 23]
3.3 flatten
ndarray.flatten()
:将数组对象展平为连续的扁平化的一维数组。
方法定义:
def flatten(self, /, order: _OrderKACF = "C") -> ndarray[tuple[int], _DType_co]: ...
参数说明:
order
:读取元素并填充新数组的索引顺序,可选:{'C','F', 'A', 'K'}
。
示例 1 :
import numpy as np
x = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
new_arr = x.flatten()
print(x) # 原数组不变
# 输出:
# [[ 1 2 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
print(new_arr)
# [ 1 2 3 4 5 6 7 8 9 10 11 12]
3.4 flat
ndarray.flat
:一维迭代器属性,允许以扁平化方式遍历或访问多维数组的所有元素。
注意事项:
- 与
flatten()
不同,flat
不复制数据,而是提供对原数组数据的直接视图。 - 支持迭代,可使用
for
循环遍历所有元素。
flat
、flatten()
和 ravel()
对比:
方法/属性 | 返回类型 | 内存复制 | 是否可修改原数据 | 适用场景 |
---|---|---|---|---|
flat | 迭代器 | 否 | 是 | 遍历或按索引访问元素(直接操作原数据) |
flatten() | 副本数组 | 是 | 否 | 需要独立的一维数据副本(隔离修改) |
ravel() | 视图数组 | 否 | 是 | 获取一维视图并保留数组结构(高效操作) |
示例 1 ,使用迭代器遍历元素:
# 创建二维数组
a = np.array([[1, 2], [3, 4]])
# 使用迭代器遍历元素
print("遍历元素:")
for elem in a.flat:
print(elem, end=' ') # 输出: 1 2 3 4