这就是我正在尝试做的事情。我在 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 和转换):
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 正在访问正在运行转换的组的名称。在pandas关于transform的文档中写道:“每个组都被赋予了属性‘名称’,以防你需要知道你正在处理哪个组。”我尝试访问 x.name,但这给出了列的名称,而不是组的名称。所以我不明白这个文档指的是什么。
IIUC,你可以这样做:
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