跳到主要内容

NumPy 核心操作速查

ndarray 用固定 dtype 描述每个元素槽位;形状 (2, 3) 表示两行三列,而不是两个独立的 Python 列表。本页范围是内存中的稠密数组,假设读者已了解 Python 索引与切片。示例 API 可用于 NumPy 1.26 和 2.x;整数推断宽度及类型提升规则可能不同,关心表示方式时应指定固定宽度类型。整数数组范围有限,可能溢出。

官方资源

导入

import numpy as np

数组创建

基础创建

# 一维数组
a = np.array([1, 2, 3], dtype=np.int64)
print(a)
# [1 2 3]
print(a.ndim)
# 1

# 多维数组
b = np.array([[1,2,3],[4,5,6]])
print(b)
# [[1 2 3]
# [4 5 6]]

数组属性

# 形状 (Shape)
b.shape # (2, 3)

# 元素数据类型 (Dtype)
a.dtype # dtype('int64')

# 浮点数数组
c = np.array([2.2, 5, 1.1])
print(c.dtype.name)
# float64
print(c)
# [2.2 5. 1.1]

初始化数组

# 全零数组
d = np.zeros((2,3))
print(d)
# [[0. 0. 0.]
# [0. 0. 0.]]

# 全一数组
e = np.ones((2,3))
print(e)
# [[1. 1. 1.]
# [1. 1. 1.]]

# 随机数数组 (0-1 之间均匀分布)
rng = np.random.default_rng(42)
print(rng.random((2, 3)))
# [[0.77395605 0.43887844 0.85859792]
# [0.69736803 0.09417735 0.97562235]]

生成序列

# 等差数列 (类似 range,但支持浮点数)
f = np.arange(10, 50, 2)
print(f)
# [10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48]

# 等间距浮点数序列
print(np.linspace(0, 2, 15))
# [0. 0.14285714 0.28571429 0.42857143 0.57142857 0.71428571
# 0.85714286 1. 1.14285714 1.28571429 1.42857143 1.57142857
# 1.71428571 1.85714286 2. ]

形状、轴与广播

广播从最右侧比较维度:对应大小必须相等,或其中一个为 1;缺少的前导维度按 1 处理。因此 (2, 3) + (3,) 会给每行加上同一个向量,而 (2, 3) + (2,) 会报错。将后者变为 (2, 1),才能每行加一个数。广播避免复制重复输入,但输出与中间结果仍需内存。

聚合的 axis 指被消去的维度:axis=0 沿行聚合,每列留下一个值;axis=1 沿列聚合,每行留下一个值。keepdims=True 保留大小为 1 的轴,便于后续广播。reshape 保持元素总数不变,只允许一个 -1 维度由程序推断。一维向量没有行列朝向,.T 不会改变形状;列向量可用 v[:, None] 构造。

x = np.arange(6).reshape(2, 3)
assert (x + np.array([10, 20, 30])).tolist() == [[10, 21, 32], [13, 24, 35]]
assert x.sum(axis=0).tolist() == [3, 5, 7]
assert x.sum(axis=1).tolist() == [3, 12]
centered = x - x.mean(axis=1, keepdims=True)
assert centered.tolist() == [[-1.0, 0.0, 1.0], [-1.0, 0.0, 1.0]]
assert x.reshape(-1).shape == (6,)

数组运算

算术运算

a = np.array([10,20,30,40])
b = np.array([1, 2, 3, 4])

# 逐元素运算 (Elementwise)
print(a - b)
# [ 9 18 27 36]
print(a * b)
# [ 10 40 90 160]

# 华氏度转摄氏度
fahrenheit = np.array([0, -10, -5, -15, 0])
celsius = (fahrenheit - 32) * (5/9)
print(celsius)
# [-17.77777778 -23.33333333 -20.55555556 -26.11111111 -17.77777778]

布尔数组

# 比较运算生成布尔数组
print(celsius > -20)
# [ True False False False True]
print(celsius % 2 == 0)
# [False False False False False]

矩阵运算

A = np.array([[1,1],[0,1]])
B = np.array([[2,0],[3,4]])

# 逐元素乘积 (Hadamard product)
print(A * B)
# [[2 0]
# [0 4]]

# 矩阵乘法 (Dot product)
print(A @ B)
# [[5 4]
# [3 4]]

类型提升 (Upcasting)

array1 = np.array([[1, 2, 3], [4, 5, 6]]) # int
array2 = np.array([[7.1, 8.2, 9.1], [10.4, 11.2, 12.3]]) # float

# 整数与浮点数相加,结果自动提升为浮点数
array3 = array1 + array2
print(array3)
# [[ 8.1 10.2 12.1]
# [14.4 16.2 18.3]]
print(array3.dtype)
# float64

聚合函数

# 常用统计量
print(array3.sum())
# 79.3
print(array3.max())
# 18.3
print(array3.min())
# 8.1
print(array3.mean())
# 13.216666666666667

# 二维数组示例
b = np.arange(1, 16, 1).reshape(3, 5)
print(b)
# [[ 1 2 3 4 5]
# [ 6 7 8 9 10]
# [11 12 13 14 15]]

索引、切片与迭代

索引

# 一维数组
a = np.array([1, 3, 5, 7])
print(a[2])
# 5

# 多维数组
a = np.array([[1, 2], [3, 4], [5, 6]])
print(a[1, 1])
# 4

# 高级索引:通过索引数组提取特定元素
print(np.array([a[0, 0], a[1, 1], a[2, 1]]))
# [1 4 6]
print(a[[0, 1, 2], [0, 1, 1]])
# [1 4 6]

布尔索引

# 利用布尔数组筛选元素
print(a > 5)
# [[False False]
# [False False]
# [False True]]
print(a[a > 5])
# [6]

切片

# 一维切片
a = np.array([0, 1, 2, 3, 4, 5])
print(a[:3])
# [0 1 2]
print(a[2:4])
# [2 3]

# 多维切片
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a[:2])
# [[1 2 3 4]
# [5 6 7 8]]
print(a[:2, 1:3])
# [[2 3]
# [6 7]]

切片与内存共享

# 基本切片返回的是视图 (View),与原数组共享内存
sub_array = a[:2, 1:3]
sub_array[0, 0] = 50
print(sub_array[0, 0])
# 50
print(a[0, 1])
# 50
print(np.shares_memory(a, sub_array))
# True

# 若需独立副本,必须显式调用 copy()
independent = a[:2, 1:3].copy()

注意:使用整数数组或布尔数组进行高级索引时,通常返回的是副本 (Copy) 而非视图。在需要确认内存是否共享时,可使用 np.shares_memory() 检查。

加载小型分隔数据集

以下示例使用 StringIO 模拟 CSV 数据,无需依赖外部文件:

from io import StringIO

csv_data = StringIO("""height,score
1.70,82
1.82,91
1.65,76
""")
records = np.genfromtxt(csv_data, delimiter=",", names=True)

print(records.dtype.names)
# ('height', 'score')
print(records["score"].mean())
# 83.0

副本、数值比较与可复现性

副本与视图的规则是明确的:基本数组切片共享数据,整数数组或布尔数组索引读取会创建副本。但 x[x < 0] = 0 这样的直接索引赋值仍会修改 xreshape 能返回视图时返回视图,否则复制;flatten() 总是复制。a + b 通常创建结果,a += b 则写回 a,不能为容纳浮点数而悄悄改变 dtype。二维矩阵乘法 (m, k) @ (k, n) 得到 (m, n)* 是逐元素乘法。

== 返回逐元素布尔数组,不是单个判断。np.array_equal 检查形状与值完全一致。浮点结果可用 np.allclose,其条件为 abs(a-b) <= atol + rtol*abs(b);容差应按问题的单位与精度选择。它允许广播,若要求形状相同,还需单独检查。除非设置 equal_nan=True,NaN 不相等。sum 等聚合会传播 NaN,nansum 则跳过它,两者采用不同的缺失值策略。

arange 不包含终点,浮点步长可能累积舍入误差;linspace 指定点数,默认包含终点。随机示例使用带种子的局部 Generator,在相同环境下重跑会从相同随机流起点开始。需要长期精确复现时,应记录 NumPy 版本和生成器;仅有种子不保证跨版本随机流一致。

expected = np.array([0.3])
actual = np.array([0.1]) + 0.2
assert not np.array_equal(actual, expected)
assert actual.shape == expected.shape
assert np.allclose(actual, expected, rtol=0, atol=1e-15)

文档

NumPy 官方文档 — 当前稳定版

NumPy 入门基础

探索关联

这篇笔记还没有文档关联。

同主题的其他笔记 (53)

打开关联网络