用跨多列的groupby减去列的平均值

时间:2021-05-10 21:52:15

标签: python pandas dataframe lambda

我在多列中使用 groupby 应用此函数时遇到问题,但跳过某些列。

我的数据框如下所示:

arr = pd.DataFrame(
[[201207310930, 0.0022, -0.0160,    0.0055, 0.0324, -0.0328],
[201207310930,  0.0040, -0.0073,    0.0293, 0.0465, -0.0275],   
[201207310930,  -0.0095,-0.0080,    0.0215, 0.0525, -0.0317],   
[201207311030,  -0.0005,-0.0040,    -0.0149,    0.0135, 0.0488],
[201207311030,  -0.0087,-0.0240,    0.0134, 0.0480, -0.0331]]
)   

我想在日期时间分组然后去趋势(减去平均值),所以这就是我尝试过的(忽略 x1 列):

detrendfunc = lambda x: (x - x.mean())
cols = arr.columns[2:]
output=df.groupby(['Datetime'])[cols].transform(detrendfunc)

我的问题是这只是输出一堆零,我认为它只是从 x 的均值中减去 x,但 x 的均值只包括一个元素,而不是一组元素。

预期结果是一个新的数据框,其中每个元素减去每列中每个组的平均值:

201207310930    0.0033  -0.00556    -0.01326    -0.0114 -0.00213
201207310930    0.0051  0.00313      0.01053    0.0027  0.00316
201207310930    -0.0084 0.00243      0.00273    0.0087  -0.001033
201207311030    0.0041  0.01        -0.01415    -0.01725  0.04095
201207311030    -0.0041 -0.01        0.01415    0.01725 -0.04095

2 个答案:

答案 0 :(得分:0)

假设您有这个 df

       Datetime      x1      x2      x3      x4      x5
0  201207310930  0.0022 -0.0160  0.0055  0.0324 -0.0328
1  201207310930  0.0040 -0.0073  0.0293  0.0465 -0.0275
2  201207310930 -0.0095 -0.0080  0.0215  0.0525 -0.0317
3  201207311030 -0.0005 -0.0040 -0.0149  0.0135  0.0488
4  201207311030 -0.0087 -0.0240  0.0134  0.0480 -0.0331

那么:

detrendfunc = lambda x: (x - x.mean())
cols = df.columns[1:]  # <-- change `arr` to `df` and `[2:]` to `[1:]`
output = df.groupby(["Datetime"])[cols].transform(detrendfunc)

df_out = pd.concat([df["Datetime"], output], axis=1)
print(df_out)

打印:

       Datetime      x1        x2        x3       x4        x5
0  201207310930  0.0033 -0.005567 -0.013267 -0.01140 -0.002133
1  201207310930  0.0051  0.003133  0.010533  0.00270  0.003167
2  201207310930 -0.0084  0.002433  0.002733  0.00870 -0.001033
3  201207311030  0.0041  0.010000 -0.014150 -0.01725  0.040950
4  201207311030 -0.0041 -0.010000  0.014150  0.01725 -0.040950

答案 1 :(得分:0)

您可以在第一列上设置索引,使用 transform 获取每个组的平均值,同时保持形状,再次使用变换进行减法,然后重新设置索引:

(arr
 .set_index(0)
 .transform(lambda df: df - df.groupby(level=0)
                              .transform("mean")
            )
 .reset_index()
 )
 
              0       1         2         3        4         5
0  201207310930  0.0033 -0.005567 -0.013267 -0.01140 -0.002133
1  201207310930  0.0051  0.003133  0.010533  0.00270  0.003167
2  201207310930 -0.0084  0.002433  0.002733  0.00870 -0.001033
3  201207311030  0.0041  0.010000 -0.014150 -0.01725  0.040950
4  201207311030 -0.0041 -0.010000  0.014150  0.01725 -0.040950

另一种选择是分别对相关列进行计算,然后 update 原始数据帧(请注意,这会覆盖原始 arr 数据帧 - 您可以在运行之前制作数据帧的副本更新):

arr.update(arr.iloc[:, 1:] - arr.groupby(0).transform("mean"))

arr
           0       1         2         3        4         5
0  201207310930  0.0033 -0.005567 -0.013267 -0.01140 -0.002133
1  201207310930  0.0051  0.003133  0.010533  0.00270  0.003167
2  201207310930 -0.0084  0.002433  0.002733  0.00870 -0.001033
3  201207311030  0.0041  0.010000 -0.014150 -0.01725  0.040950
4  201207311030 -0.0041 -0.010000  0.014150  0.01725 -0.040950