速通指南:把 NumPy 的 13 个核心章节浓缩成一条主线,全程用一个「全班 5 位同学 × 3 门课成绩表」串起来。看完就能直接上手处理 Excel 表格数据,深挖再看对应章节的独立文章。

NumPy 是什么?

NumPy(Numerical Python)是 Python 科学计算的基础库,核心是 ndarray(N 维数组)对象。

用 Python 自带的列表处理大量数值时,又慢又占内存;而 ndarray 把同类型的元素紧密排列在连续内存中,运算速度能快几十倍。它是 Pandas、SciPy、scikit-learn、深度学习框架等几乎所有数据科学工具的底层基石。

想用 Python 做数据处理、机器学习,NumPy 是绕不开的第一步。

🎯 本篇主线案例:班主任手上有 5 位同学、3 门课(语文/数学/英语)的成绩单。接下来每一节,我们都用这同一份数据来演示——学完你会发现,13 个知识点其实是一套连贯的"成绩处理流水线"。

1. 创建数组

一切的起点:怎么创建各种 ndarray。

import numpy as np

# 从列表创建:5 位同学 × 3 门课的成绩表(行=同学,列=语文/数学/英语)
scores = np.array([[90, 80, 85],
                   [60, 70, 65],
                   [95, 88, 92],
                   [72, 65, 78],
                   [55, 60, 70]])

# 特殊数组
zeros = np.zeros((2, 3))        # 全 0
ones = np.ones((2, 3))          # 全 1
arange = np.arange(0, 10, 2)    # 等差数列,输出: [0 2 4 6 8]
linspace = np.linspace(0, 1, 5) # 等分,输出: [0.   0.25 0.5  0.75 1.  ]

⚠️ 灵魂警告:Python 原生 int 是任意精度的,但 NumPy 数组默认用固定位宽的整数(64 位系统上一般是 int64)。当你把超大整数塞进数组,或者整型数组做除法时,结果可能静默溢出(32 位环境下尤其危险)。数据要精确、要算小数,请显式指定:np.array([...], dtype=np.float64)。

2. 数组属性

每个数组都有几个关键属性,决定它长什么样。

arr = np.array([[1, 2, 3], [4, 5, 6]])

arr.shape   # 输出: (2, 3)   2 行 3 列
arr.ndim    # 输出: 2        几维数组
arr.size    # 输出: 6        元素总数
arr.dtype   # 输出: int64    元素类型

💡 shape 是最重要的属性:后面所有广播、统计的 axis 逻辑都跟它有关。看到数组先问一句"它 shape 是多少"。

3. 索引与切片

像列表一样索引,但支持多维,还有强大的"花式索引"。回到成绩表:第 1 位同学(索引 0)各科成绩是 [90, 80, 85]。

scores[0, 1]   # 输出: 80   第 1 位同学(行0)的数学(列1)
scores[:, 1]   # 输出: [80 70 88 65 60]   全班同学的数学成绩
scores[1, :]   # 输出: [60 70 65]         第 2 位同学全部成绩
scores[::-1]   # 输出: 把 5 行倒序
scores[[0, 2, 4], :]  # 花式索引:只取第 1、3、5 位同学

⚠️ 灵魂警告(新手最大噩梦):切片返回的是视图(浅拷贝),不是副本!reshape 同理。修改视图会污染原数组:

first = scores[0]      # 视图
first[0] = 999         # ⚠️ scores[0,0] 也会变成 999!

想得到一份独立的数据,务必用 .copy():safe = scores[0].copy()。凡是"我要单独改一份,不能影响原来的",都先 .copy()。

4. 数组运算

逐元素运算,和普通数学符号几乎一致。给全班每门课都加 5 分平时分:

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

a + b       # 输出: [5 7 9]
a * b       # 输出: [4 10 18]
a ** 2      # 输出: [1 4 9]
a > 2       # 输出: [False False True]

scores + 5  # 全班每门课都加 5 分(标量运算,见第 8 节广播)

5. 形状操作

重塑、展平、转置——调整数组的"长相"。

arr = np.arange(12)

arr.reshape(3, 4)   # 输出: 3 行 4 列(元素总数不变)
arr.flatten()       # 输出: 展平成一维
arr.T               # 输出: 转置,行列互换

⚠️ 灵魂警告:reshape 返回的也是视图,与切片一样共享底层数据。确认元素总数(size)没变才能 reshape,否则报错。要独立副本用 arr.reshape(3, 4).copy()。

另外,转置 scores.T 会让 shape 从 (5, 3) 变成 (3, 5)——“行=同学、列=科目"变成"行=科目、列=同学”,做统计时方向完全不同,别搞混。

6. 通用函数(ufunc)

对数组逐元素应用数学函数,速度快(底层用 C 实现,比 Python 循环快几十倍)。

arr = np.array([1, 4, 9])

np.sqrt(arr)   # 输出: [1. 2. 3.]
np.exp(arr)    # 输出: 指数
np.log(arr)    # 输出: 对数

💡 ufunc 都能配 where 或 out 参数做"只算部分/就地写入",但那是进阶玩法。新手记住:凡是"对每个元素做同一个数学运算",先想到 ufunc,别写 for 循环。

7. 统计与聚合

求总和、均值、最大值,以及最重要的 axis 参数。回到成绩表:

np.sum(scores)          # 输出: 总分(所有 15 个成绩相加)
np.mean(scores)         # 输出: 平均分
np.mean(scores, axis=0) # 输出: [75.5 72.6 78. ]  每门课全班平均
np.max(scores, axis=1)  # 输出: [90 70 95 78 70]  每位同学最高分
np.argmax(scores, axis=1)  # 输出: [0 2 0 2 2]  每位同学最高分在哪科(0=语文)

💡 axis=0 沿着行方向压缩(对每一"列"统计);axis=1 沿着列方向压缩(对每一"行"统计)。记不住就记口诀:axis 指"要消掉的那一维"——axis=0 消掉行 → 得到每列的结果。

8. 广播机制(重点 & 难点)

不同形状的数组也能运算——小的自动"扩展"到大的形状。给全班每门课加上各自的"难度加成":

scores + 10                     # 标量广播:每个元素 +10
scores + np.array([5, 3, 4])    # 行广播:3 门课各加不同分 → 每行都加

广播是怎么"补形状"的?规则是从最后一个维度往前逐个对齐:

scores:  (5, 3)
加成:        (3,)
               ↑ 对齐到倒数第 1 维,都是 3,直接算
        → 加成自动变成 (5, 3),每行加同一份
scores:  (5, 3)
加成2:      (5, 1)
               ↑ 倒数第 1 维 1 ≠ 3,但 1 可以广播
        → 加成2 自动变成 (5, 3),每列加同一份

规则一句话:从最后一个维度往前比,维度相同直接算,维度为 1 则广播,都不匹配则报错。

⚠️ 灵魂警告:(3,) 和 (1, 3) 看着"差不多",但广播结果完全不一样——前者逐行加,后者逐列加(因为 1 在倒数第 1 维)。报 ValueError: operands could not be broadcast together with shapes (5,3) (4,) 时,别慌,就是最后对不齐,检查一下两个数组的 shape。

9. 布尔索引与筛选

用条件筛选出想要的元素——数据处理的常用手法。找出不及格的同学:

scores < 60
# 输出: 每个元素是 True/False 的"掩码"

scores[scores < 60]           # 输出: [55  ...]  所有不及格的分数

# np.where:条件成立取 x,不成立取 y —— 数据清洗高频场景
np.where(scores < 60, 0, scores)   # 不及格的全改成 0

np.where 的多条件逻辑才是它最强的地方,配合 &(且)、|(或):

# 数学 60 分以上、且 语文 65 分以上的同学:留原分,否则置 0
math_col = scores[:, 1]
chinese_col = scores[:, 0]
np.where((math_col >= 60) & (chinese_col >= 65), scores, 0)

⚠️ 灵魂警告:用 & 和 |,不是 Python 的 and / or(那个会报错:truth value of an array is ambiguous)。而且每个条件都要用括号包起来,否则优先级会出错。

10. 数组拼接与分割

把多个数组合并,或者把一个拆开。

a = np.array([1, 2])
b = np.array([3, 4])

np.concatenate([a, b])   # 输出: [1 2 3 4]   沿现有轴拼接
np.vstack([a, b])        # 输出: [[1 2] [3 4]]  垂直堆叠成两行
np.hstack([a, b])        # 输出: [1 2 3 4]      水平拼接
np.split(a, 2)           # 输出: 分割成若干块

💡 拼成绩表:来了两位新同学,np.vstack([scores, new_students]) 就能把新行追加进去。想加一门新课(新列)用 np.hstack 或 np.column_stack。

11. 文件读写

把数组保存到磁盘,下次直接加载——处理完成绩单别忘了存档。

np.save("scores.npy", scores)   # 保存单个数组(.npy 二进制)
loaded = np.load("scores.npy")  # 加载,输出: shape 还是 (5, 3)
np.savez("data.npz", s=scores, b=b)  # 保存多个数组(.npz 压缩)

⚠️ 灵魂警告:np.load 后拿到的数组记得确认 dtype 和 shape 没变(旧存档可能是别的版本生成的)。.npy 存的是二进制,跨机器没问题;想给人看 / 给 Excel 用,用 np.savetxt("scores.csv", scores, delimiter=",")。

12. 随机数

生成随机数组,可复现的种子。给全班生成一份模拟的体育成绩:

rng = np.random.default_rng(42)   # 新版推荐接口,固定种子 42,结果可复现

rng.random((2, 3))      # 均匀分布 [0, 1)
rng.normal(70, 10, 5)   # 正态分布:均值 70、标准差 10,输出 5 个
rng.integers(0, 10, 5)  # 随机整数 [0, 10)

⚠️ 灵魂警告:请用 np.random.default_rng()(新版 Generator API),别再用 np.random.random() / np.random.seed()(旧版)。新版基于 PCG-64 算法,随机质量更好、更快,而且天然支持并行(每个进程一个独立 rng,不会互相干扰);旧版的 np.random.seed() 是全局状态,多线程/并行场景下极易踩坑。

13. 线性代数基础

矩阵乘法、求逆、解方程——科学计算的看家本领,也是最小二乘拟合的根基。

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

A @ A                  # 矩阵乘法(@ 或 np.matmul)——注意 A 得是方阵
np.linalg.inv(A)       # 逆矩阵
np.linalg.det(A)       # 行列式
np.linalg.eig(A)       # 特征值 & 特征向量

真正的高频场景是解线性方程组(数据分析里的最小二乘法就是解这种方程):

# 例:3x + 2y = 8
#     2x -  y = 3
A = np.array([[3, 2], [2, -1]])
b = np.array([8, 3])

x = np.linalg.solve(A, b)   # 输出: [2. 1.]  即 x=2, y=1
np.allclose(A @ x, b)       # 输出: True     验证:代回原方程成立

💡 A @ x == b 的写法在浮点运算下别用 == 判断,用 np.allclose(允许微小误差)。解方程前先 np.linalg.det(A) 看看行列式是否非 0——为 0 说明无唯一解(奇异矩阵)。

结语

这 13 个知识点串起来就是一条完整的 NumPy 主线:创建 → 属性 → 索引 → 运算 → 形状 → ufunc → 统计 → 广播 → 筛选 → 拼接 → IO → 随机 → 线代。

回到我们的成绩表:从 np.array 建表(第 1 节)→ 看 shape(第 2 节)→ 取某人某科(第 3 节)→ 加平时分(第 4 节)→ 算每科平均(第 7 节)→ 按行广播加成(第 8 节)→ 筛不及格(第 9 节)→ 拼接新同学(第 10 节)→ 存档(第 11 节)——这一整套就是最朴素的"成绩处理流水线",Excel 能做的,这 13 节全都能做。

每一章都有对应的独立文章可以深挖,尤其是 广播机制 和 花式索引 这两个难点,值得单独反复看。

📚 配套系列:13 章详细版

速通是主线,每章还有一篇独立的详细文章,想深挖哪章点哪章:

章节 内容
第 1 章 创建数组 np.array、zeros、ones、arange、linspace
第 2 章 数组属性 shape、ndim、size、dtype
第 3 章 索引与切片 基本索引、切片、花式索引
第 4 章 数组运算 逐元素运算、标量运算
第 5 章 形状操作 reshape、flatten、ravel、转置
第 6 章 通用函数 sqrt、exp、log 等 ufunc
第 7 章 统计与聚合 sum、mean、max、axis
第 8 章 广播机制 ⭐ 重点难点
第 9 章 布尔索引与筛选 条件筛选、掩码、where
第 10 章 数组拼接与分割 concatenate、vstack、hstack、split
第 11 章 文件读写 save、load、.npy / .npz
第 12 章 随机数 random、种子、常见分布
第 13 章 线性代数基础 矩阵乘法、inv、det、solve、eig

💡 学习建议:光看懂了不算会,合上文章亲手敲一遍,报错的地方就是还没真懂的地方。