发布于2026-07-10 阅读(0)
扫一扫,手机访问
在数据处理中,经常需要根据样本所属的类别,从参考表里取出对应的行,然后对原始数据逐行做运算——比如相减。这种需求看上去不复杂,但实际操作中,很多初学者会在 Pandas 的 transform 和 apply 之间犯迷糊,特别是当它们与组名访问搅在一起的时候。
先明确一个关键点:transform 的设计初衷是“列内统一变换”,它并不暴露当前分组的分组键值。你可能在文档里看到过“Each group is endowed the attribute ‘name’”这样的描述,但这里有个容易踩的坑:这个“name”属性,只有在 apply 传入的子 DataFrame 中才有效;在 transform 的 lambda 函数里,你接收到的是一列 Series,它的 x.name 指的是列名(比如 'A'),而不是分组键(比如 1 或 2)。
所以,下面这种写法是行不通的:
# ❌ 错误示范:transform 中 x 是 Series,x.name 是列名,无法用于 df_ref 定位 df.groupby(cat).transform(lambda x: x - df_ref.loc[x.name])
那么,正确的做法是什么?这里有三种思路,推荐直接从第一种开始。
这是最简洁、性能也最优的方案。核心思路是利用 cat 这个类别序列,对 df_ref 做一次重排(reindex),生成一个与 df 行数完全对齐的参考矩阵,然后直接相减,一次广播,搞定所有行。
import numpy as np
import pandas as pd
n_cols, n_samples = 3, 4
df = pd.DataFrame(np.arange(n_samples * n_cols).reshape(n_samples, n_cols), columns=list('ABC'))
cat = pd.Series([1, 1, 2, 2])
df_ref = pd.DataFrame(np.zeros((2, n_cols)), index=[1, 2], columns=list('ABC'))
df_ref.loc[1] = 10
# ✅ 向量化,一行解决(原地修改)
result = df.copy()
result -= df_ref.reindex(cat).values # reindex 返回 DataFrame,.values 转为 ndarray 实现广播
# 或者返回新 DataFrame(推荐,避免副作用)
result = df.sub(df_ref.reindex(cat).values)
print(result)
输出结果:
A B C 0 -10.0 -9.0 -8.0 1 -7.0 -6.0 -5.0 2 6.0 7.0 8.0 3 9.0 10.0 11.0
⚠️ 注意:
df_ref.reindex(cat)会按照cat的顺序([1,1,2,2])重复选取df_ref.loc[1]和df_ref.loc[2]。加上.values是为了确保以 NumPy 数组参与广播运算,从而避免索引对齐带来的额外开销。
当逻辑比较复杂,需要依赖分组键来做条件判断时,apply 才是正确选择。它的 lambda 函数接收的是一个完整的子 DataFrame,而这个子 DataFrame 确实拥有 name 属性,指向当前组的分组键值。
result = df.groupby(cat, group_keys=False).apply(lambda x: x - df_ref.loc[x.name])
这里的 x.name 就是 1 或 2,可以安全地用于 df_ref.loc[]。加上 group_keys=False 参数,可以防止结果索引中额外添加组键层级,保持原始行顺序。
用原始的 for 循环虽然直观,但丧失了向量化带来的性能优势,而且代码扩展性差,容易出错:
# ❌ 避免:显式索引遍历,性能差,不易扩展
result = df.copy()
for i in range(len(df)):
result.iloc[i] -= df_ref.loc[cat.iloc[i]]
transform 不提供组名访问能力,它的设计目标就是列内统一变换,x.name 永远返回列名,这点务必记牢。apply 的子 DataFrame 才拥有 name 属性(即分组键值),适用于需要依赖分组上下文的逻辑。reindex().values 方案:零循环、高可读、全向量化,充分利用了 Pandas 的索引对齐和 NumPy 的广播机制,这才是真正做到“优雅”的方式。groupby。很多时候,换个思路,问题会简单得多。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8