数据科学 1 · NumPy¶
先说清楚:数据科学/数值计算是 Python 的绝对统治领域,而 Java 在这里几乎没有等价生态(
ND4J/EJML等冷门、社区小)。所以本篇的"Java 对照"会变弱——不是"翻译 Java",而是"带你进入 Java 程序员陌生的、Python 最强的一面"。会用"近邻概念"(数组、循环、SQL、Excel)帮你建立直觉,但很多地方没有 Java 等价物,那正是要学的。
NumPy 是 Python 数据科学生态的地基(Pandas、scikit-learn、PyTorch 都建立在它之上)。核心是 ndarray——多维、固定类型、向量化运算的数组。
1.1 ndarray:和 Java 数组是两回事¶
-
Java 数组
-
NumPy ndarray
ndarray 的关键特性:
- 固定 dtype(所有元素同类型,如
int64/float64)——这是性能的来源(连续内存、C 层操作)。 - 多维:
np.array([[1,2,3],[4,5,6]])是 2×3 矩阵(.shape、.ndim、.dtype)。 - 逐元素运算:
a + b、a * 2、a > 0自动作用到每个元素。
a = np.array([[1, 2, 3], [4, 5, 6]])
a.shape # (2, 3)
a.ndim # 2
a.dtype # int64
a.sum() # 21(所有元素)
a.mean(axis=0) # 每列均值
1.2 向量化:NumPy 的灵魂(vs for 循环)¶
这是 NumPy 最该理解的一点:不要写 for 循环遍历数组,用向量化运算——底层 C 批量处理,快 50–100 倍。
-
Python for 循环(慢)
-
NumPy 向量化(快)
为什么快:固定 dtype → 连续内存 + 向量化 SIMD 指令 + 无解释器开销。Java 程序员的直觉:像 C 数组运算,而非 ArrayList 逐个装箱。
NumPy 铁律
能向量化就别写循环。看到一个对大数组的 for,先想"能不能用 ndarray 运算替掉"。
1.3 广播(broadcasting):没有 Java 对应¶
形状不同的数组相加,NumPy 会广播——把小数组"拉伸"到大数组的形状,无需复制。这是 Java 程序员完全陌生的能力。
a = np.array([[1, 2, 3],
[4, 5, 6]]) # 形状 (2, 3)
b = np.array([10, 20, 30]) # 形状 (3,)
a + b
# array([[11, 22, 33],
# [14, 25, 36]]) # b 被广播到每一行
规则:从右向左对齐维度,各维度要么相等、要么其中一个是 1(或缺失),才能广播。
a = np.ones((3, 4))
a + np.array([1, 2, 3, 4]) # (3,4) + (4,) → 广播,OK
a + np.array([1, 2, 3]) # (3,4) + (3,) → 维度不匹配,ValueError
实战用途:数据标准化(每列减均值除标准差)、批量加偏置——一行搞定,无需循环。
1.4 索引与切片¶
a = np.arange(12).reshape(3, 4)
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
a[1, 2] # 6(第 1 行第 2 列)
a[0] # 第 0 行:array([0,1,2,3])
a[:, 1] # 第 1 列:array([1,5,9])
a[0:2, 1:3] # 子矩阵
布尔索引(按条件筛选,对照 SQL 的 WHERE):
花式索引(按索引数组取):
切片是视图
NumPy 切片返回视图(共享内存),修改会影响原数组(和 Python list 切片的副本不同)。要独立副本用 .copy()。
1.5 通用函数(ufunc)¶
元素级运算,都是 C 实现的 ufunc:
1.6 线性代数¶
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
A @ B # 矩阵乘法(@ 运算符)
A.T # 转置
np.linalg.inv(A) # 逆矩阵
np.linalg.solve(A, b) # 解线性方程组 Ax=b
对照 Java:你大概会用 Apache Commons Math 或 EJML——但 NumPy 是事实标准、API 远更简洁、生态环绕它。
1.7 与 Java 对照小结¶
| 概念 | Java 近邻 | NumPy |
|---|---|---|
| 多维数组 | int[][](原始)/ EJML 矩阵 |
ndarray(统一、向量化) |
| 逐元素运算 | 手写循环 | a + b(向量化) |
| 广播 | 无(手写循环) | 自动 |
| 布尔筛选 | Stream filter | a[a > 0] |
| 矩阵运算 | Commons Math/EJML | A @ B、np.linalg.* |
诚实结论:Java 没有等价物。学 NumPy 不是"换个语法",是"获得一种 Java 给不了的能力"。
本章练习¶
练习 1.1
生成 100 万个随机数,分别用 Python 循环和 NumPy 向量化求平方和,对比耗时。
练习 1.2
用广播把一个 (3,4) 的数组每列减去该列均值(标准化第一步)。
练习 1.3
给定成绩数组,用布尔索引选出 60–80 分(含)的学生。
← 回首页 | 下一章:数据科学 2 · Pandas