【问题标题】:Subtracting mean of columns with groupby across multiple columns用 groupby 跨多个列减去列的平均值
【发布时间】:2021-05-10 21:52:15
【问题描述】:

我无法在多列中将此函数与 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

【问题讨论】:

  • 变量arr里面是什么?
  • 具有日期时间、x1、x2...x5 的数据框
  • 你能编辑你的代码并把预期的结果放在那里吗?
  • OK 我已经添加了预期的结果并展示了如何创建 arr。

标签: python pandas dataframe lambda


【解决方案1】:

假设你有这个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

【讨论】:

    【解决方案2】:

    您可以在第一列设置索引,使用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
    

    【讨论】:

    • 你知道对于 ~50GB 数据帧来说哪个最快?
    • 最后一个可能是最快的,因为它只计算每个组的平均值一次,而其他选项计算每个组中每个元素的每个组的平均值?
    • 对于50GB,可能不会想到Pandas
    • 你会推荐什么
    • 将其转储到 sql 中?也许使用 sqlite。或者如果你熟悉 R,你可以使用data.table。在 python 中,你可以使用pydatatable。不过,我首先会选择 SQLite,并且我假设您对 SQL 有一些了解(这类似于 windows 操作)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 2022-01-09
    相关资源
    最近更新 更多