在Python中考虑以下DataFrame
:
import pandas as pd
df = pd.DataFrame({'id':[0]*3+[1]*3,'y':np.random.randn(6),'x':np.random.randn(6)})
给出
id y x
0 0 0.721757 1.595646
1 0 0.359601 1.128473
2 0 1.134922 2.317929
3 1 0.290152 -1.901336
4 1 0.128742 0.982683
5 1 0.556914 0.745208
请注意,y
和x
是根据id
分组的。我要创建以下DataFrame
id y x y_md x_md
0 0 0.721757 1.595646 -0.017003 -0.085037
1 0 0.359601 1.128473 -0.379159 -0.552209
2 0 1.134922 2.317929 0.396162 0.637246
3 1 0.290152 -1.901336 -0.035117 -1.843521
4 1 0.128742 0.982683 -0.196527 1.040498
5 1 0.556914 0.745208 0.231644 0.803023
其中
y_md
包含与其组平均值的偏差值(id
= 0
&1
)x_md
包含与其组平均值的偏差值(id
= 0
&1
)我想到的是
df_g = df.groupby('id')
yy = pd.Series( df['y'].values - df_g['y'].mean().repeat(3).values )
xx = pd.Series( df['x'].values - df_g['x'].mean().repeat(3).values )
pd.concat([df,yy.rename('y_md'), xx.rename('x_md')],axis=1)
但是对我来说看起来并不好。我想知道是否有一个优雅的班轮或类似的结果吗?非常感谢您的帮助。
答案 0 :(得分:2)
使用GroupBy.transform
处理多列,用DataFrame.sub
减去,用DataFrame.add_suffix
更改列名,然后用DataFrame.join
附加到原始列:
c = ['x','y']
df = df.join(df[c].sub(df.groupby('id')[c].transform('mean')).add_suffix('_md'))
print (df)
id y x x_md y_md
0 0 0.721757 1.595646 -0.085037 -0.017003
1 0 0.359601 1.128473 -0.552210 -0.379159
2 0 1.134922 2.317929 0.637246 0.396162
3 1 0.290152 -1.901336 -1.843521 -0.035117
4 1 0.128742 0.982683 1.040498 -0.196527
5 1 0.556914 0.745208 0.803023 0.231645
或者可以分配新的列名称:
df[['x_md','y_md']] = df[['x','y']].sub(df.groupby('id')[['x','y']].transform('mean'))
答案 1 :(得分:1)
将id
设置为索引,对索引进行分组,然后从df中减去分组的平均值:
df = df.set_index("id")
df[['y_md','x_md']] = df.sub(df.groupby("id").agg("mean"))
df
y x y_md x_md
id
0 0.721757 1.595646 -0.017003 -0.085037
0 0.359601 1.128473 -0.379159 -0.552210
0 1.134922 2.317929 0.396162 0.637246
1 0.290152 -1.901336 -0.035117 -1.843521
1 0.128742 0.982683 -0.196527 1.040498
1 0.556914 0.745208 0.231645 0.803023