从零开始的数据分析之旅
NumPy是Python科学计算的基石。它的核心是ndarray(N-dimensional array)——一个高效的多维数组对象,支持向量化运算、广播机制和丰富的数学函数。掌握NumPy是学习Pandas、Scikit-learn等库的前提。
import numpy as np
# 基本创建
a = np.array([1, 2, 3, 4, 5])
b = np.zeros((3, 4)) # 3×4零矩阵
c = np.ones((2, 3)) # 2×3全1矩阵
d = np.arange(0, 10, 2) # [0, 2, 4, 6, 8]
e = np.linspace(0, 1, 5) # [0, 0.25, 0.5, 0.75, 1.0]
# 随机数组
np.random.seed(42)
r1 = np.random.rand(3, 3) # 均匀分布 [0, 1)
r2 = np.random.randn(3, 3) # 标准正态分布
r3 = np.random.randint(0, 10, (3, 3)) # 整数 [0, 10)
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
# 三种矩阵乘法写法
C1 = A @ B # Python 3.5+ 推荐写法
C2 = A.dot(B) # 方法调用
C3 = np.matmul(A, B) # 函数调用
# 结果: [[19 22], [43 50]]
# 行列式和逆矩阵
print(f"行列式: {np.linalg.det(A):.1f}") # -2.0
print(f"逆矩阵:\n{np.linalg.inv(A).round(2)}") # [[-2. 1.], [1.5 -0.5]]
# 特征值与特征向量
eigenvalues, eigenvectors = np.linalg.eig(A)
print(f"特征值: {eigenvalues.round(2)}") # [-0.37 5.37]
# 解方程组: 2x + y = 5, x + 3y = 10
A = np.array([[2, 1], [1, 3]])
b = np.array([5, 10])
x = np.linalg.solve(A, b)
print(f"x={x[0]:.2f}, y={x[1]:.2f}") # x=1.0, y=3.0
广播是NumPy最强大的特性之一,允许不同形状的数组进行运算,无需显式复制数据。
# 广播示例
row = np.array([[1, 2, 3]]) # 1×3
col = np.array([[10], [20]]) # 2×1
result = row + col # 2×3
# 结果:
# [[11 12 13],
# [21 22 23]]
# 标准化每一列
data = np.random.randn(100, 5) # 100×5
mean = data.mean(axis=0) # 1×5
std = data.std(axis=0) # 1×5
normalized = (data - mean) / std # 广播: (100×5) - (1×5)
| 索引类型 | 语法 | 特点 |
|---|---|---|
| 基本索引 | arr[0, 1] | 返回视图(修改影响原数组) |
| 切片 | arr[0:2, :] | 返回视图 |
| 布尔索引 | arr[arr > 0] | 返回副本 |
| 花式索引 | arr[[0, 2, 4]] | 返回副本 |
data = np.arange(12).reshape(3, 4)
# [[ 0 1 2 3],
# [ 4 5 6 7],
# [ 8 9 10 11]]
# 布尔索引:选大于5的元素
print(data[data > 5]) # [6, 7, 8, 9, 10, 11]
# 花式索引:选第0行和第2行
print(data[[0, 2]])
# [[0, 1, 2, 3], [8, 9, 10, 11]]
# 组合索引
print(data[1, [0, 2, 3]]) # 第1行的0,2,3列: [4, 6, 7]
import numpy as np
np.random.seed(42)
data = np.random.randn(1000)
print(f"均值: {data.mean():.4f}")
print(f"中位数: {np.median(data):.4f}")
print(f"方差: {data.var():.4f}")
print(f"标准差: {data.std():.4f}")
print(f"极差: {data.ptp():.4f}")
# 分位数
print(f"Q1: {np.percentile(data, 25):.4f}")
print(f"Q3: {np.percentile(data, 75):.4f}")
# 累积运算
arr = np.array([1, 2, 3, 4, 5])
print(f"累积和: {np.cumsum(arr)}")
print(f"累积积: {np.cumprod(arr)}")
arr = np.arange(12)
matrix = arr.reshape(3, 4)
row_vec = arr.reshape(1, -1) # 行向量
col_vec = arr.reshape(-1, 1) # 列向量
# flatten vs ravel
flat1 = matrix.flatten() # 副本
flat2 = matrix.ravel() # 视图(可能)
# 转置
print(matrix.T)
# 拼接
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
print(np.vstack([a, b])) # 垂直
print(np.hstack([a, b.T])) # 水平
reshape(-1, n)中-1表示自动计算该维度大小,非常方便。#!/usr/bin/env python3
# NumPy — 完整实战
import numpy as np
# ============ 数组创建 ============
a = np.array([1, 2, 3, 4, 5])
b = np.zeros((3, 4))
c = np.ones((2, 3))
d = np.arange(0, 10, 2)
e = np.linspace(0, 1, 5)
print(f"arange: {d}")
print(f"linspace: {e}")
# ============ 矩阵运算 ============
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(f"矩阵乘法:\n{A @ B}")
print(f"转置:\n{A.T}")
print(f"行列式: {np.linalg.det(A):.1f}")
print(f"逆矩阵:\n{np.linalg.inv(A).round(2)}")
# ============ 广播 ============
row = np.array([[1, 2, 3]])
col = np.array([[10], [20]])
print(f"广播:\n{row + col}")
# ============ 高级索引 ============
data = np.arange(12).reshape(3, 4)
print(f"原始:\n{data}")
print(f"布尔索引>5: {data[data > 5]}")
print(f"花式索引[0,2]:\n{data[[0, 2]]}")
# ============ 统计与线性代数 ============
arr = np.random.randn(1000)
print(f"均值: {arr.mean():.4f}, 标准差: {arr.std():.4f}")
eigenvalues = np.linalg.eig(A)[0]
print(f"特征值: {eigenvalues.round(2)}")
x = np.array([0, np.pi/2, np.pi])
print(f"sin: {np.sin(x).round(4)}")
print(f"exp(0): {np.exp(0):.1f}")
print("\n✅ Python验证通过 — 矩阵运算/广播/索引")
| 技巧 | 慢代码 | 快代码 | 加速比 |
|---|---|---|---|
| 向量化 | for循环 | np运算 | 10-100x |
| 预分配 | list.append | np.zeros+索引 | 5-10x |
| 广播 | 循环+复制 | 形状对齐 | 3-5x |
| 视图 | copy() | 切片/reshape | 2-10x |
| 类型 | object数组 | 指定dtype | 5-20x |