【问题标题】:pandas substraction by column value熊猫按列值减去
【发布时间】:2020-10-08 07:33:35
【问题描述】:

我在 pandas 数据框中有一个时间序列,该数据框与月份有一行。我打电话给df1。然后我通过 group_by 获得每月平均值,我将结果数据框称为 df2。现在我想在不使用循环的情况下减去每列的月平均值。也就是说,df2 中的“month==1”行需要从 df1 中“month”==1 的所有行中减去。

在 numpy 中,我将重塑矩阵,执行操作(由于 numpy 广播)并再次重塑它。但我不知道这样做的熊猫方法是什么。尽管我觉得这应该是一种超级简单的方法。

这是一个示例,我使用双 for 循环以非常低效的方式执行此操作。

import pandas as pd

df1 = pd.DataFrame({'month': [1, 1, 1, 2, 2, 3, 3, 3, 4, 4],
                   'value': [51, 16, 17, 25, 28, 37, 39, 73, 84, 56],
                    'value2': [551, 165, 175, 255, 258, 375, 359, 735, 854, 556]})


df2 = df1.groupby(["month"]).mean()
df2["month"] = [1,2,3,4]

for mon in range(1, 5):
    for val in ["value", "value2"]:
        mon_mean = float(df2.loc["month"] == mon, [val])
        df1.loc[df1["month"] == mon, [val]] = df1.loc[df1["month"] == mon, [val]].apply(lambda x: x- mon_mean)

欢迎您使用任何线索或 pandas 函数。

编辑

如果不是将 df2 减去 df1,而是将第三个数据帧,即 df3 的行数比 df1 多,你会怎么做。所以扩展前面的例子:

import pandas as pd

df1 = pd.DataFrame({'month': [1, 1, 2, 2, 3, 3, 4, 4],
                    'value': [51, 16, 17, 25, 28, 37, 39, 73],
                    'value2': [551, 165, 175, 255, 258, 375, 359, 735, ]})

df3 = pd.DataFrame({'month': [1, 1, 1, 2, 2, 3, 3, 3, 4, 4],
                    'value': [43, 32, 54, 54, 54, 35, 76, 65, 35, 74],
                    'value2': [745, 346, 175, 889, 543, 876, 345, 876, 345, 987]})

df2 = df1.groupby(["month"]).mean()
df2["month"] = [1, 2, 3, 4]

for mon in range(1, 5):
    for val in ["value", "value2"]:
        mon_mean = float(df2[df2["month"] == mon][val])
        print(mon_mean)
        df3.loc[df3["month"] == mon, [val]] = df3.loc[df3["month"] == mon, [val]].apply(lambda x: x - mon_mean)
print(df3)
month  value  value2
0      1    9.5   387.0
1      1   -1.5   -12.0
2      1   20.5  -183.0
3      2   33.0   674.0
4      2   33.0   328.0
5      3    2.5   559.5
6      3   43.5    28.5
7      3   32.5   559.5
8      4  -21.0  -202.0
9      4   18.0   440.0

【问题讨论】:

    标签: python pandas dataframe array-broadcasting


    【解决方案1】:

    GroupBy.transform 用于由聚合值填充的新DataFrame,因此可能只减去DataFrame.sub 列表c 中的过滤列:

    c = ["value", "value2"]
    df1[c] = df1[c].sub(df1.groupby(["month"])[c].transform('mean'))
    print (df1)
       month      value      value2
    0      1  23.000000  254.000000
    1      1 -12.000000 -132.000000
    2      1 -11.000000 -122.000000
    3      2  -1.500000   -1.500000
    4      2   1.500000    1.500000
    5      3 -12.666667 -114.666667
    6      3 -10.666667 -130.666667
    7      3  23.333333  245.333333
    8      4  14.000000  149.000000
    9      4 -14.000000 -149.000000
    

    详情

    print (df1.groupby(["month"])[c].transform('mean'))
           value      value2
    0  28.000000  297.000000
    1  28.000000  297.000000
    2  28.000000  297.000000
    3  26.500000  256.500000
    4  26.500000  256.500000
    5  49.666667  489.666667
    6  49.666667  489.666667
    7  49.666667  489.666667
    8  70.000000  705.000000
    9  70.000000  705.000000
    

    编辑:对于另一个 DataFrame 中的减法使用 month 转换为索引 by DataFrame.set_index 以按月匹配数据:

    c = ["value", "value2"]
    df2 =  df1.groupby(["month"])[c].mean()
    
    df3 = df3.set_index('month')[c].sub(df2).reset_index()
    print (df3)
       month  value  value2
    0      1    9.5   387.0
    1      1   -1.5   -12.0
    2      1   20.5  -183.0
    3      2   33.0   674.0
    4      2   33.0   328.0
    5      3    2.5   559.5
    6      3   43.5    28.5
    7      3   32.5   559.5
    8      4  -21.0  -202.0
    9      4   18.0   440.0
    

    【讨论】:

    • 我扩展了这个问题,因为我意识到我的例子不够准确。
    • @Xbel - 我尝试运行编辑代码并得到KeyError: 'month' - 是否可以添加预期的输出来测试我的新解决方案?
    • @jerzal 更正并添加了预期的输出。很抱歉给您带来不便。
    • 谢谢你。我会更频繁地使用 Pandas,并深入了解所有这些功能。它们非常有用。
    猜你喜欢
    • 2020-01-05
    • 1970-01-01
    • 2020-05-16
    • 2013-12-10
    • 2020-07-06
    • 2015-07-02
    • 2019-02-05
    • 2018-03-07
    相关资源
    最近更新 更多