本节前言
函数应用是将自定义逻辑批量作用于数据的核心机制。本节覆盖元素级(map)、行 / 列级(apply、applymap)、管道(pipe)以及聚合 / 变换(agg、transform、eval、query)。
1. map()
Series 专用,对每个元素应用函数或字典映射,返回新 Series。
s = pd.Series([1, 2, 3])
# 函数映射
s.map(lambda x: x * 10)
# 0 10
# 1 20
# 2 30
# 字典映射
s.map({1: 'one', 2: 'two', 3: 'three'})
# 0 one
# 1 two
# 2 threemap 与 replace 区别
map遇到字典中不存在的键返回 NaN。replace保留不匹配的原始值。- pandas 2.1+ 中
DataFrame.map()取代了DataFrame.applymap(),但Series.map()语义保持不变。
2. apply()
Series / DataFrame 通用。
- Series:对每个元素应用函数(与 map 类似)。
- DataFrame:沿
axis对每行或每列应用函数。
df = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
# DataFrame:默认对每列(axis=0)应用
df.apply(lambda col: col.sum())
# A 3
# B 7
# 对每行应用
df.apply(lambda row: row.sum(), axis=1)
# 0 4
# 1 6
# 返回多个值
df.apply(lambda col: (col.min(), col.max()))apply 的性能警告
apply是 Python 循环的封装,并非真正的向量化。性能敏感场景应尽量使用向量化操作或agg/transform。
3. applymap()
DataFrame 专用,对 DataFrame 的每个元素逐一遍历应用函数。
df.applymap(lambda x: x * 2)
# A B
# 0 2 6
# 1 4 8pandas 2.1 变更
DataFrame.applymap()在 pandas 2.1 中已被弃用,推荐使用DataFrame.map()。- 新代码建议使用
df.map()。- 注意
Series.map()与DataFrame.map()语义不同。
4. pipe()
函数管道调用,将前面的对象作为第一个参数传入函数,适合链式操作。
def add_one(df):
return df + 1
def multiply(df, factor):
return df * factor
# 传统写法
multiply(add_one(df), 3)
# pipe 写法
df.pipe(add_one).pipe(multiply, factor=3)
# 也支持 (func, kwargs) 元组
df.pipe((multiply, 'factor'), 3)| 方式 | 写法 |
|---|---|
| 普通调用 | func(df, *args, **kwargs) |
| pipe 调用 | df.pipe(func, *args, **kwargs) |
pipe 的价值
- 让代码从左到右阅读,减少嵌套。
- 便于复用数据清洗流水线。
5. agg() / aggregate()
对 Series / DataFrame 执行一个或多个聚合操作,返回标量汇总结果。
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
# 单一聚合
df.agg('sum')
# A 6
# B 15
# 多个聚合
df.agg(['sum', 'mean', 'max'])
# A B
# sum 6 15
# mean 2 5
# max 3 6
# 每列不同聚合
df.agg({'A': 'sum', 'B': ['mean', 'std']})
# 自定义函数
df.agg(lambda x: x.max() - x.min())aggregate 与 agg 完全等价,是同一个方法的别名。
6. transform()
对数据执行函数并返回与输入相同形状的结果。
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
# 标准化(每列)
df.transform(lambda x: (x - x.mean()) / x.std())
# 多个变换
df.transform(['sqrt', 'abs'])
# 每列不同变换
df.transform({'A': 'sqrt', 'B': 'abs'})| 方法 | 返回形状 | 用途 |
|---|---|---|
agg() | 标量汇总 | 统计摘要 |
transform() | 原始形状 | 逐元素变换、标准化 |
apply() | 灵活 | 通用函数应用 |
与 groupby 的关系
GroupBy.agg()和GroupBy.transform()是分组聚合的核心方法,详见 十六、分组与聚合(如大纲扩展笔记)。
7. eval()
使用字符串表达式进行向量化计算。
df = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
# DataFrame.eval()
df.eval('C = A + B')
# A B C
# 0 1 3 4
# 1 2 4 6
# 局部变量
df.eval('C = A + @factor', local_dict={'factor': 10})
# pd.eval():通用表达式
pd.eval('A + B', local_dict={'A': df['A'], 'B': df['B']})性能优势
eval()避免创建中间 Python 对象,在大 DataFrame 上性能优于普通表达式。
8. query()
使用字符串表达式筛选 DataFrame 的行。
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
df.query('A > 1')
# A B
# 1 2 5
# 2 3 6
# 多条件
df.query('A > 1 and B < 6')
# 引用外部变量
threshold = 2
df.query('A > @threshold')
# 列名含空格
df.query('`my col` > 1')query 与布尔索引
df.query('A > 1')等价于df[df['A'] > 1],但更简洁、更贴近 SQL 习惯。