NumPy入门:5分钟搞懂Python数值计算的基石
上个月有个实习生问我:「哥,Python列表不是能存数字吗,为啥还要学NumPy?」
我让他跑了一行代码:
import timea = list(range(1000000))b = list(range(1000000))c = [x + y for x, y in zip(a, b)]
跑了 0.15 秒。然后换成 NumPy:
import numpy as npa = np.arange(1000000)b = np.arange(1000000)c = a + b
0.003 秒。
快了 50 倍。 他不说话了。
为什么 NumPy 这么快?
Python 列表存的是「对象指针」,每个数字都是一个独立的 Python 对象。NumPy 数组存的是连续的内存块,CPU 可以一次性处理一大片数据。
简单说:Python 列表是散装的,NumPy 是整箱的。
搞数值计算、数据分析、机器学习,NumPy 是地基。Pandas、Matplotlib、Scikit-learn 全都建在它上面。
创建数组:4 种常用方式
import numpy as np# 1. 从 Python 列表转换a = np.array([1, 2, 3, 4, 5])# 2. 创建全零/全一数组zeros = np.zeros(5) # [0. 0. 0. 0. 0.]ones = np.ones((2, 3)) # 2行3列的全1矩阵# 3. 创建等差数列arr = np.arange(0, 10, 2) # [0 2 4 6 8]arr = np.linspace(0, 1, 5) # [0. 0.25 0.5 0.75 1. ]# 4. 创建随机数组rand = np.random.rand(3, 3) # 3x3 随机矩阵,0-1之间rand_int = np.random.randint(1, 100, size=5) # 5个随机整数
arange 和 linspace 的区别:arange 指定步长,linspace 指定个数。想均匀分割用 linspace,想固定间隔用 arange。
数组操作:切片、变形、拼接
切片跟列表差不多,但更灵活
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])arr[0, 1] # 第0行第1列 → 2arr[:, 0] # 所有行的第0列 → [1, 4, 7]arr[1, :] # 第1行所有列 → [4, 5, 6]arr[arr > 5] # 布尔索引,取大于5的元素 → [6, 7, 8, 9]
踩坑提醒:切片返回的是「视图」不是「副本」。改切片会改原数组:
a = np.array([1, 2, 3, 4, 5])b = a[1:3]b[0] = 99print(a) # [ 1 99 3 4 5],原数组被改了!
想要副本,用 a[1:3].copy()。
变形:reshape
arr = np.arange(12)matrix = arr.reshape(3, 4) # 变成 3x4 矩阵print(matrix)# [[ 0 1 2 3]# [ 4 5 6 7]# [ 8 9 10 11]]
-1 是偷懒写法,让 NumPy 自动算维度:
arr.reshape(3, -1) # 3行,列数自动算 → 3x4arr.reshape(-1, 6) # 列数6,行数自动算 → 2x6
拼接
a = np.array([1, 2, 3])b = np.array([4, 5, 6])np.concatenate([a, b]) # [1 2 3 4 5 6]np.stack([a, b]) # [[1 2 3], [4 5 6]],增加一个维度np.vstack([a, b]) # 垂直拼接,按行np.hstack([a, b]) # 水平拼接,按列
运算:向量化才是精髓
NumPy 的核心优势是「向量化运算」——不用写循环,直接对整个数组操作:
a = np.array([1, 2, 3, 4, 5])a * 2 # [ 2 4 6 8 10],每个元素都乘2a ** 2 # [ 1 4 9 16 25],每个元素平方np.sqrt(a) # [1. 1.41 1.73 2. 2.24],开根号np.exp(a) # 指数运算np.log(a) # 对数运算
两个数组之间也能直接运算:
a = np.array([1, 2, 3])b = np.array([4, 5, 6])a + b # [5 7 9]a * b # [4 10 18],对应位置相乘,不是矩阵乘法!a.dot(b) # 32,点积(矩阵乘法用这个)
注意:* 是逐元素相乘,矩阵乘法用 @ 或者 .dot()。这个坑我见过好几个人踩。
常用统计函数
arr = np.array([3, 1, 4, 1, 5, 9, 2, 6])arr.mean() # 平均值 3.875arr.sum() # 求和 31arr.max() # 最大值 9arr.min() # 最小值 1arr.std() # 标准差arr.var() # 方差np.median(arr) # 中位数 3.5np.percentile(arr, 75) # 75%分位数
多维数组可以指定轴方向:
matrix = np.array([[1, 2, 3], [4, 5, 6]])matrix.sum(axis=0) # 按列求和 → [5 7 9]matrix.sum(axis=1) # 按行求和 → [6 15]
广播机制:不同形状也能运算
NumPy 有个很爽的特性叫「广播」——形状不同的数组也能运算:
matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])vector = np.array([10, 20, 30])matrix + vector# [[11 22 33]# [14 25 36]# [17 28 39]]
vector 自动「广播」到每一行。不用手动循环,代码干净很多。
写在最后
NumPy 的东西很多,但核心就这几个:创建数组、切片索引、向量化运算、统计函数。掌握了这些,80% 的场景都能搞定。
剩下的高级特性(如结构化数组、高级索引、线性代数),用到再查文档就行。