Pythonnumpy统计与数学指南并不只看表面做法,关键还要理解相关条件、限制和后续影响。
import numpy as nparr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])# 集中趋势print(arr.mean()) # 5.5(均值)print(np.mean(arr)) # 同上(函数形式)print(np.median(arr)) # 5.5(中位数)print(np.average(arr)) # 5.5(加权平均,可传 weights)# 分位数print(np.percentile(arr, 25)) # 3.25(第 25 百分位)print(np.percentile(arr, 50)) # 5.5(= 中位数)print(np.percentile(arr, 75)) # 7.75print(np.quantile(arr, 0.25)) # 同上(0~1 之间)print(np.quantile(arr, [0.25, 0.5, 0.75])) # 一次算多个# 离散程度print(arr.std()) # 2.87(标准差)print(arr.var()) # 8.25(方差)print(np.ptp(arr)) # 9(极差 = max - min)# 极值print(arr.min()) # 1print(arr.max()) # 10print(arr.sum()) # 55# 累积print(arr.cumsum()) # [1 3 6 10 15 21 28 36 45 55](前缀和)print(arr.cumprod()) # 累积乘积
mat = np.arange(12).reshape(3, 4)# [[ 0 1 2 3]# [ 4 5 6 7]# [ 8 9 10 11]]# axis=0: 沿行方向(压缩行,对每列操作)print(mat.sum(axis=0)) # [12 15 18 21] — 每列求和print(mat.mean(axis=0)) # [4. 5. 6. 7.] — 每列均值print(mat.max(axis=0)) # [ 8 9 10 11] — 每列最大值# axis=1: 沿列方向(压缩列,对每行操作)print(mat.sum(axis=1)) # [ 6 22 38] — 每行求和print(mat.mean(axis=1)) # [1.5 5.5 9.5] — 每行均值# keepdims: 保持维度print(mat.sum(axis=1, keepdims=True)) # (3, 1) 而非 (3,)# [[ 6]# [22]# [38]]
axis=0 沿行方向(垂直向下)→ 压缩行,得到每列的统计axis=1 沿列方向(水平向右)→ 压缩列,得到每行的统计axis 小口诀: axis=0 是"纵向压扁", axis=1 是"横向压扁"
arr = np.array([1, 2, 3, 4, 5, 6])# 相关系数x = np.array([1, 2, 3, 4, 5])y = np.array([2, 4, 5, 4, 5])print(np.corrcoef(x, y))# [[1. 0.774597]# [0.774597 1. ]]# 直方图(计数)hist, bin_edges = np.histogram(arr, bins=3)print(hist) # [2 2 2]print(bin_edges) # [1. 2.667 4.333 6. ]# 数字化(找每个值落入哪个 bin)bins = np.array([0, 3, 7, 10])print(np.digitize([1, 5, 8, 9], bins)) # [1 2 3 3]# 加权平均values = np.array([1, 2, 3, 4])weights = np.array([0.1, 0.2, 0.3, 0.4])print(np.average(values, weights=weights)) # 3.0# 协方差print(np.cov(x, y))# 差异print(np.diff(arr)) # [1 1 1 1 1] — 相邻差print(np.diff(arr, n=2)) # [0 0 0 0] — 二阶差分# 梯度(多维偏导)mat = np.array([[1, 2, 6], [3, 4, 5]])print(np.gradient(mat)) # 每个维度的梯度# 排序print(np.sort([3, 1, 4, 1, 5])) # [1 1 3 4 5]arr = np.array([3, 1, 4, 1, 5])arr.sort() # 原地排序# argsort: 返回排序后的索引idx = np.argsort([3, 1, 4, 1, 5])print(idx) # [1 3 0 2 4] — 按值排序后的原索引# argmax / argmin: 极值索引arr = np.array([10, 5, 30, 20])print(arr.argmax()) # 2(最大值 30 的位置)print(arr.argmin()) # 1(最小值 5 的位置)# NaN 安全版本arr = np.array([1.0, np.nan, 3.0, np.nan, 5.0])print(np.nanmean(arr)) # 3.0(忽略 NaN)print(np.nanstd(arr)) # 忽略 NaN 的标准差print(np.nansum(arr)) # 忽略 NaN 的求和print(np.nan_to_num(arr, nan=0)) # NaN → 0: [1. 0. 3. 0. 5.]
A = np.array([[1, 2], [3, 4]])B = np.array([[5, 6], [7, 8]])
# 矩阵乘法print(A @ B)print(np.dot(A, B))print(np.matmul(A, B))# 矩阵求逆print(np.linalg.inv(A))# [[-2. 1. ]# [ 1.5 -0.5]]# 矩阵的幂print(np.linalg.matrix_power(A, 3)) # A @ A @ A# 行列式print(np.linalg.det(A)) # -2.0# 迹print(np.trace(A)) # 1 + 4 = 5# 转置print(A.T)# 秩print(np.linalg.matrix_rank(A)) # 2# 条件数print(np.linalg.cond(A))
eigenvalues, eigenvectors = np.linalg.eig(A)print(eigenvalues) # [-0.3723 5.3723]print(eigenvectors)# 验证: A·v = λ·vfor i in range(len(eigenvalues)): Av = A @ eigenvectors[:, i] lv = eigenvalues[i] * eigenvectors[:, i] print(np.allclose(Av, lv)) # True
U, S, Vt = np.linalg.svd(A)print(U.shape, S.shape, Vt.shape) # (2,2) (2,) (2,2)# 重构: A = U @ diag(S) @ VtA_reconstructed = U @ np.diag(S) @ Vtprint(np.allclose(A, A_reconstructed)) # True
# 解 Ax = bA = np.array([[3, 1], [1, 2]])b = np.array([9, 8])x = np.linalg.solve(A, b)print(x) # [2. 3.]print(A @ x) # [9. 8.] ✓# 最小二乘解(超定/欠定方程组)A = np.array([[1, 1], [1, 2], [1, 3]])b = np.array([1, 2, 2])x, residuals, rank, s = np.linalg.lstsq(A, b, rcond=None)print(x) # [0.6667 0.5 ] — 最佳拟合
v = np.array([3, 4])print(np.linalg.norm(v)) # L2: 5.0 (默认)print(np.linalg.norm(v, ord=1)) # L1: 7.0print(np.linalg.norm(v, ord=np.inf)) # L∞: 4.0# 矩阵范数print(np.linalg.norm(A, ord='fro')) # Frobenius: sqrt(1²+2²+3²+4²)print(np.linalg.norm(A, ord=2)) # 谱范数(最大奇异值)
# QR 分解Q, R = np.linalg.qr(A)# Cholesky 分解(需对称正定)A_spd = np.array([[4, 1], [1, 3]])L = np.linalg.cholesky(A_spd)print(L @ L.T) # 等于 A_spd# LU 分解from scipy.linalg import lu# SciPy 提供更完整的分解# 张量点积A = np.arange(24).reshape(2, 3, 4)B = np.arange(20).reshape(4, 5)print(np.tensordot(A, B, axes=([2], [0])).shape) # (2, 3, 5)
# 创建随机数生成器rng = np.random.default_rng(seed=42)# 均匀分布rng.uniform(0, 1, 10) # [0,1) 均匀rng.integers(0, 100, 10) # [0,100) 整数rng.random(10) # 等同于 uniform(0, 1)# 正态分布rng.standard_normal((3, 4)) # N(0, 1)rng.normal(loc=5, scale=2, size=(3, 4)) # N(5, 4)# 其他分布rng.exponential(scale=1.0, size=10) # 指数分布rng.poisson(lam=3, size=10) # 泊松分布rng.binomial(n=10, p=0.5, size=10) # 二项分布rng.chisquare(df=2, size=10) # 卡方分布rng.gamma(shape=2, scale=1, size=10) # Gamma 分布rng.beta(a=2, b=5, size=10) # Beta 分布rng.laplace(loc=0, scale=1, size=10) # 拉普拉斯分布rng.lognormal(mean=0, sigma=1, size=10) # 对数正态# 排列与抽样arr = np.array([1, 2, 3, 4, 5])rng.shuffle(arr) # 原地打乱print(rng.permutation(arr)) # 返回打乱副本print(rng.choice(arr, size=3, replace=False)) # 不放回抽样print(rng.choice(arr, size=10, replace=True)) # 有放回抽样print(rng.choice(arr, size=3, p=[0.1, 0.1, 0.3, 0.3, 0.2])) # 带概率
# 旧版(全局状态,不推荐新代码使用)np.random.seed(42)np.random.rand(3, 4) # [0,1) 均匀np.random.randn(3, 4) # N(0,1)np.random.randint(0, 100, (3, 4)) # 整数np.random.normal(0, 1, (3, 4)) # 正态np.random.uniform(0, 1, (3, 4)) # 均匀np.random.shuffle(arr) # 打乱np.random.choice(arr, 5) # 抽样
# 新版rng = np.random.default_rng(42)result1 = rng.normal(0, 1, 1000)# 旧版np.random.seed(42)result2 = np.random.randn(1000)# 确保整个程序的随机性都可复现RANDOM_SEED = 42rng = np.random.default_rng(RANDOM_SEED)
| 需求 | 代码 |
|---|---|
| 均值 | arr.mean() / np.mean(arr) |
| 中位数 | np.median(arr) |
| 标准差 | arr.std() |
| 方差 | arr.var() |
| 总和 | arr.sum() |
| 沿轴求和 | arr.sum(axis=0) |
| 分位数 | np.percentile(arr, 50) |
| 最小值索引 | arr.argmin() |
| 最大值索引 | arr.argmax() |
| 相邻差 | np.diff(arr) |
| 排序索引 | np.argsort(arr) |
| 相关系数 | np.corrcoef(x, y) |
| 直方图 | np.histogram(arr, bins=10) |
| NaN 安全均值 | np.nanmean(arr) |
| 矩阵乘法 | A @ B |
| 求逆 | np.linalg.inv(A) |
| 行列式 | np.linalg.det(A) |
| 特征值 | np.linalg.eig(A) |
| SVD | np.linalg.svd(A) |
| 解方程 | np.linalg.solve(A, b) |
| 范数 | np.linalg.norm(v) |
| 随机种子 | rng = np.random.default_rng(42) |
| 正态分布 | rng.standard_normal(shape) |
| 均匀分布 | rng.uniform(0, 1, shape) |
| 打乱 | rng.shuffle(arr) |
| 抽样 | rng.choice(arr, size=5) |
