pandas 按列值减法
pandas substraction by column value
我在 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,而是第三个数据帧,即比 df1 行数更多的 df3,你会怎么做。所以扩展前面的例子:
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
仅使用 GroupBy.transform
for new DataFrame
filled by aggregate values, so possible subtract by 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
按 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
我在 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,而是第三个数据帧,即比 df1 行数更多的 df3,你会怎么做。所以扩展前面的例子:
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
仅使用 GroupBy.transform
for new DataFrame
filled by aggregate values, so possible subtract by 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
按 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