NumPy 2.x 完全指南【十四】基础操作 & 改变数组形状

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'),控制 srcdst` 的数据类型转换。
  • 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:新形状,类型为 intint 元组,必须与原形状兼容。
  • 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 顺序

CC-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]]

FF-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 循环遍历所有元素。

flatflatten()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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨 禹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值