获取pandas groupby transform中的组名

2 投票
2 回答
37 浏览
提问于 2025-04-13 19:57

我想做的是这样的。我在pandas中有一个数据框(DataFrame):

import numpy as np
import pandas as pd

n_cols = 3
n_samples = 4
df = pd.DataFrame(np.arange(n_samples * n_cols).reshape(n_samples, n_cols), columns=list('ABC'))
print(df)

输出结果:

   A   B   C
0  0   1   2
1  3   4   5
2  6   7   8
3  9  10  11

每一行数据都有一个类别:

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
print(df_ref)

输出结果:

      A     B     C
1  10.0  10.0  10.0
2   0.0   0.0   0.0

我想用更优雅的方式来完成以下操作(比如,使用groupby和transform):

result = df.copy()
for i in range(n_cols):
  result.iloc[i] = df.iloc[i] - df_ref.loc[cat[i]]
print(results)

输出结果:

    A   B   C
0 -10  -9  -8
1  -7  -6  -5
2   6   7   8
3   9  10  11

我觉得像这样应该可以工作:

df.groupby(cat).transform(lambda x: x - df_ref.loc[x.GROUP_NAME])

这里的x.GROUP_NAME是用来获取正在进行transform操作的组的名称。在pandas的transform文档中写道:“每个组都有一个‘name’属性,以便你知道自己在处理哪个组。”我尝试访问x.name,但那给出的却是列的名称,而不是组的名称。所以我不明白这个文档所指的是什么。

2 个回答

1

如果我理解正确的话,你可以这样做:

df = df.set_index(cat)
df = df - df_ref

print(df)

输出结果是:

      A     B     C
1 -10.0  -9.0  -8.0
1  -7.0  -6.0  -5.0
2   6.0   7.0   8.0
2   9.0  10.0  11.0
1

其实不需要用到 groupby,只要用 reindex 来调整 df_ref 的索引,然后转换成数组就可以了:

df -= df_ref.reindex(cat).values

或者,如果你想要一个副本的话:

out = df.sub(df_ref.reindex(cat).values)

需要注意的是,你的方法也可以用 groupby.apply 来实现:

out = df.groupby(cat, group_keys=False).apply(lambda x: x - df_ref.loc[x.name])

输出结果:

      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

撰写回答