我有以下数据框(我们称之为 data
):
id | type | val1 | val2 |
-------------------------
1 | A | 10.1 | 11.0 |
1 | B | 10.5 | 11.2 |
2 | A | 10.7 | 10.9 |
2 | B | 10.6 | 11.1 |
3 | A | 10.3 | 10.5 |
3 | B | 10.4 | 11.3 |
并且我想为每个 A
为每个 B
获取类型 A
和 B
(id
-valX
) 之间的差异} 列,即我希望结果是:
id | val1 | val2 |
------------------
1 | -0.4 | -0.2 |
2 | 0.1 | -0.2 |
3 | -0.1 | -0.8 |
我能做到这一点的唯一方法是定义一个函数:
def getDelta(df, valName):
return df[ df['type']=='A' ][valName].values[0] - df[ df['type']=='B' ][valName].values[0]
并将其分别应用于每一列:
data.groupby('id').apply(getDelta,valName='val1')
然后合并结果以获得我想要的。
有没有更有效的方法来做到这一点?最后,我想将函数应用于分组数据帧的列的子集,但此函数必须考虑另一列的值。
答案 0 :(得分:2)
就目前而言,您可以使用 np.subtract.reduce
,假设在所有情况下 'A' 出现在 'B' 之前,并且没有重复项:
df.groupby("id", sort = False).agg(np.subtract.reduce).reset_index()
id val1 val2
0 1 -0.4 -0.2
1 2 0.1 -0.2
2 3 -0.1 -0.8
答案 1 :(得分:1)
您可以旋转数据框:
x = df.pivot(index="id", columns="type", values="val1")
y = df.pivot(index="id", columns="type", values="val2")
df = pd.concat([x["A"] - x["B"], y["A"] - y["B"]], axis=1).rename(
columns={0: "val1", 1: "val2"}
)
print(df)
打印:
val1 val2
id
1 -0.4 -0.2
2 0.1 -0.2
3 -0.1 -0.8
答案 2 :(得分:1)
您可以 groupby()
您的 ID 列并在您的 diff(-1)
列上使用 valX
。将操作包装在 concat()
中,您会得到您想要的结果吗。
df.set_index('id',inplace=True)
pd.concat([df.groupby(['id'])[df.filter(like='val').columns.tolist()].diff(-1).dropna()]).reset_index()
id val1 val2 val3
0 1 -0.4 -0.2 -3.1
1 2 0.1 -0.2 17.0
2 3 -0.1 -0.8 1.5
我添加了一个额外的 valX 只是为了说明目的。