【问题标题】:Calculating rolling average per group in pandas df计算熊猫df中每组的滚动平均值
【发布时间】:2020-11-24 12:38:41
【问题描述】:

我有一个这样的df

date        car     model       mpg
1           ford    focus       10
1           ford    fiesta      15
1           ford    mustang     20
2           ford    focus       13
2           ford    fiesta      16
2           ford    mustang     27
3           ford    focus       13
3           ford    mustang     27
4           ford    focus       12
4           ford    fiesta      17

我想为每组date, car, model 添加一个window = 2date 的列rolling_mean,这样我就有一个像这样的df:

date        car     model       mpg     rolling_avg
1           ford    focus       10      nan
1           ford    fiesta      15      nan
1           ford    mustang     20      nan
2           ford    focus       13      11.5
2           ford    fiesta      16      15.5
2           ford    mustang     27      23.5
3           ford    focus       13      13
3           ford    mustang     27      27
4           ford    focus       12      12.5
4           ford    fiesta      17      Because fiesta is not in date=3, I want to (17+0)/2 = 8.5

我尝试了什么:

df_test.groupby(['date','car','model'])[['mpg']].rolling(window=2).mean().reset_index()
    date    car model   level_3 mpg
0   1   ford    fiesta  1       NaN
1   1   ford    focus   0       NaN
2   1   ford    mustang 2       NaN
3   2   ford    fiesta  4       NaN
4   2   ford    focus   3       NaN
5   2   ford    mustang 5       NaN
6   3   ford    focus   6       NaN
7   3   ford    mustang 7       NaN
8   4   ford    fiesta  9       NaN
9   4   ford    focus   8       NaN

不确定level_3 代表什么。在尝试实现我想要的结构时,我的错误在哪里?

这是使用的数据:

df = pd.DataFrame({'date':[1,1,1,2,2,2,3,3,4,4],
                   'car':['ford','ford','ford','ford','ford','ford','ford','ford','ford','ford'],
                   'model':['focus','fiesta','mustang','focus','fiesta','mustang','focus','mustang','focus','fiesta'],
                   'mpg':[10,15,20,13,16,27,13,27,12,17]})

【问题讨论】:

  • 不要按日期分组。每个日期您只有一个模型。所以你只能得到大小为 1 的组。只需使用 df.groupby(['car','model'])[['mpg']].rolling(window=2).mean().reset_index()
  • 问题不在于您按日期、汽车和型号对DataFrame进行分组,而它只应按汽车和型号分组?通过按日期、汽车和型号对其进行分组,每一行本身就是一个组,这就是您收到 NaN 值的原因。
  • 这是有道理的,但是,我希望 date 存在,以便我可以按日期绘制滚动平均值如何变化的图表。

标签: python pandas


【解决方案1】:

对我来说,首先通过DataFrame.set_indexSeries.unstack 重塑值,如果没有添加匹配0,则使用rolling,最后通过DataFrame.stack 重塑并通过DataFrame.join 添加新列:

s = (df.set_index(['date','car','model'])['mpg']
        .unstack(fill_value=0)
        .rolling(window=2)
        .mean()
        .stack()
        .rename('rolling_avg')
        )

df = df.join(s, on=['date','car','model'])
print (df)
   date   car    model  mpg  rolling_avg
0     1  ford    focus   10          NaN
1     1  ford   fiesta   15          NaN
2     1  ford  mustang   20          NaN
3     2  ford    focus   13         11.5
4     2  ford   fiesta   16         15.5
5     2  ford  mustang   27         23.5
6     3  ford    focus   13         13.0
7     3  ford  mustang   27         27.0
8     4  ford    focus   12         12.5
9     4  ford   fiesta   17          8.5

编辑:如果set_indexunstack 失败,则有重复,如:

df = pd.DataFrame({'date':[1,1,1,2,2,2,3,3,4,4],
                   'car':['ford','ford','ford','ford','ford','ford','ford','ford','ford','ford'],
                   'model':['focus','focus','mustang','focus','focus','mustang','focus','mustang','focus','fiesta'],
                   'mpg':[10,15,20,13,16,27,13,27,12,17]})

print (df)
   date   car    model  mpg
0     1  ford    focus   10 <- dupe 1  ford    focus
1     1  ford    focus   15 <- dupe 1  ford    focus
2     1  ford  mustang   20
3     2  ford    focus   13 <- dupe 2  ford    focus
4     2  ford    focus   16 <- dupe 2  ford    focus
5     2  ford  mustang   27
6     3  ford    focus   13
7     3  ford  mustang   27
8     4  ford    focus   12
9     4  ford   fiesta   17

然后如果可能首先需要唯一对,这里通过聚合sum(或mean 喜欢需要):

df1 = df.pivot_table(index=['date','car'], 
                     columns='model', 
                     values='mpg', 
                     aggfunc='sum', 
                     fill_value=0)
print (df1)
model      fiesta  focus  mustang
date car                         
1    ford       0     25       20
2    ford       0     29       27
3    ford       0     13       27
4    ford      17     12        0

然后可以使用rolling,输出与输入数据不同,因为唯一的'date','car','model'

df1 = (df1.rolling(window=2)
        .mean()
        .stack(dropna=False)
        .rename('rolling_avg')
        .reset_index()
        )

print (df1)
  
    date   car    model  rolling_avg
0      1  ford   fiesta          NaN
1      1  ford    focus          NaN
2      1  ford  mustang          NaN
3      2  ford   fiesta          0.0
4      2  ford    focus         27.0
5      2  ford  mustang         23.5
6      3  ford   fiesta          0.0
7      3  ford    focus         21.0
8      3  ford  mustang         27.0
9      4  ford   fiesta          8.5
10     4  ford    focus         12.5
11     4  ford  mustang         13.5

【讨论】:

  • 谢谢,不过,当我在df 上使用它时,我在.unstack(fill_value=0) 行得到Index contains duplicate entries, cannot reshape。你知道这可能是什么原因吗?我确实在所有列中都有重复条目,尽管与我上面的示例 df 相同。
  • @JonasPalačionis - 添加了可能的解决方案,但需要聚合,不确定是否适合您。如果不是,我的EDIT 中更改的样本数据应该会输出什么?
  • 谢谢你,一如既往。
猜你喜欢
  • 2019-11-24
  • 1970-01-01
  • 2019-11-19
  • 2021-12-10
  • 1970-01-01
  • 2020-08-09
  • 2019-11-24
  • 2019-07-27
  • 2015-01-12
相关资源
最近更新 更多