NumPy 核心操作
问题
NumPy 是什么?ndarray 和 Python 列表有什么区别?什么是广播机制?
答案
NumPy 是 Python 科学计算的基石,Pandas 的底层就是 NumPy。数据分析师主要掌握数组创建、向量化运算和广播机制即可。
ndarray vs Python list
| 对比 | Python list | NumPy ndarray |
|---|---|---|
| 类型 | 可混合类型 | 同一类型 |
| 性能 | 慢(Python 循环) | 快(C 底层运算) |
| 内存 | 大(每个元素是对象) | 小(连续内存) |
| 运算 | 不支持向量化 | 支持向量化 |
| 维度 | 一维嵌套 | 多维数组 |
性能对比
import numpy as np
# Python list 遍历求和
python_list = list(range(1000000))
result = sum(python_list) # ~50ms
# NumPy 向量化求和
np_array = np.arange(1000000)
result = np_array.sum() # ~1ms,快 50 倍
数组创建
创建 ndarray
import numpy as np
# 从列表创建
arr = np.array([1, 2, 3, 4])
arr_2d = np.array([[1, 2], [3, 4]]) # 二维
# 快捷创建
np.zeros((3, 4)) # 3x4 全零矩阵
np.ones((2, 3)) # 2x3 全一矩阵
np.full((2, 3), 7) # 2x3 全 7
np.eye(3) # 3x3 单位矩阵
np.arange(0, 10, 2) # [0, 2, 4, 6, 8]
np.linspace(0, 1, 5) # [0, 0.25, 0.5, 0.75, 1.0]
# 随机数
np.random.rand(3, 4) # 均匀分布 [0, 1)
np.random.randn(3, 4) # 标准正态分布
np.random.randint(1, 100, size=(3, 4)) # 随机整数
np.random.seed(42) # 设置随机种子(可复现)
向量化运算
向量化运算
a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
# 逐元素运算(无需循环)
a + b # [11, 22, 33, 44]
a * b # [10, 40, 90, 160]
a ** 2 # [1, 4, 9, 16]
a > 2 # [False, False, True, True]
# 聚合函数
a.sum() # 10
a.mean() # 2.5
a.std() # 1.118
a.min() # 1
a.max() # 4
a.argmax() # 3(最大值的索引)
np.median(a) # 2.5
广播机制 (Broadcasting)
广播是 NumPy 最重要的概念之一,让不同形状的数组可以一起运算:
广播示例
# 标量广播
arr = np.array([1, 2, 3])
arr * 10 # [10, 20, 30] —— 标量 10 "广播"到每个元素
# 一维 + 二维
matrix = np.array([[1, 2, 3], [4, 5, 6]]) # shape (2, 3)
row = np.array([10, 20, 30]) # shape (3,)
matrix + row # [[11, 22, 33], [14, 25, 36]] —— row 广播到每一行
广播规则
- 从右侧开始逐维度对齐
- 维度相等,或其中一个为 1,则可广播
- 不满足则报错
ValueError
条件操作
条件操作(对应 Pandas 的 np.where/np.select)
scores = np.array([85, 92, 67, 45, 78])
# np.where(二选一)
np.where(scores >= 60, '及格', '不及格')
# np.select(多条件)
conditions = [scores >= 90, scores >= 60]
choices = ['优秀', '及格']
np.select(conditions, choices, default='不及格')
# ['及格', '优秀', '及格', '不及格', '及格']
# 布尔索引
scores[scores >= 80] # [85, 92]
在 Pandas 中的常见应用
NumPy 在 Pandas 中的应用
import pandas as pd
import numpy as np
df = pd.DataFrame({'score': [85, 92, 67, 45], 'name': ['A', 'B', 'C', 'D']})
# 条件赋值
df['level'] = np.where(df['score'] >= 60, 'Pass', 'Fail')
# 多条件赋值
conditions = [df['score'] >= 90, df['score'] >= 70, df['score'] >= 60]
choices = ['A', 'B', 'C']
df['grade'] = np.select(conditions, choices, default='D')
# 对数/指数变换(处理偏态数据)
df['log_score'] = np.log1p(df['score'])
# 百分位截断
lower = np.percentile(df['score'], 5)
upper = np.percentile(df['score'], 95)
df['score_clipped'] = np.clip(df['score'], lower, upper)
常见面试问题
Q1: NumPy 为什么比 Python list 快?
答案:
- 连续内存:ndarray 元素类型相同,在内存中连续存储,CPU 缓存命中率高
- C 底层实现:运算在 C/Fortran 层面批量执行,跳过 Python 解释器开销
- 向量化:利用 CPU SIMD 指令并行处理多个元素
- 无装箱:Python list 每个元素是 Python 对象(有类型信息开销),ndarray 直接存储裸数据
Q2: 数据分析师需要掌握 NumPy 到什么程度?
答案:
- 必须掌握:
np.where、np.select(条件赋值)、聚合函数、随机数 - 了解即可:广播机制、reshape、矩阵运算
- 无需深入:线性代数、傅里叶变换等(除非做机器学习)
- 日常以 Pandas 为主,NumPy 是补充
Q3: np.nan 注意事项?
答案:
np.nan是 float 类型,整数列有 NaN 会自动转为 floatnp.nan != np.nan为 True(NaN 不等于任何值,包括自身)- 比较用
pd.isna()或np.isnan(),不要用== - Pandas 2.0+ 支持
pd.NA(可以在整数列中表示缺失)