【问题标题】:Pandas - moving averages - use values of previous X entries for current rowPandas - 移动平均线 - 使用当前行的先前 X 条目的值
【发布时间】:2018-06-03 05:22:22
【问题描述】:

所以我的数据集如下所示:

date,site,iso,id,hits
2017-08-25,google,1,7012,14225.0
2017-08-26,google,1,7012,14565.0
2017-08-27,google,1,7012,14580.0
2017-08-28,google,1,7012,14227.0
2017-08-29,google,1,7012,14568.0
2017-08-30,google,1,7012,14582.0
2017-08-31,google,1,7012,14214.0
2017-09-01,google,1,7012,14053.0
2017-08-25,facebook,2,7019,21225.0
2017-08-26,facebook,2,7019,21565.0
2017-08-27,facebook,2,7019,31580.0
2017-08-28,facebook,2,7019,13227.0
2017-08-29,facebook,2,7019,22568.0
2017-08-30,facebook,2,7019,44582.0
2017-08-31,facebook,2,7019,32214.0
2017-09-01,facebook,2,7019,44053.0

我需要使用之前 3 天的数据找到点击次数的 3 天移动平均值。 到目前为止我所做的是:

#sort values
df_sorted = df.sort_values(['site', 'iso', 'id', 'date'], ascending=[1, 1, 1, 1])
#group
df_grouped_sorted = df_sorted.groupby(['site', 'iso', 'id'], as_index=False)
df_sorted['mov_av_hits'] = df_grouped_sorted[['hits']].rolling(3, min_periods=3).mean().fillna(0).reset_index(
    0, drop=True)

现在我的数据集看起来像这样:

date,site,iso,id,hits,hits_avg
2017-08-25,google,1,7012,14225.0,14146.0
2017-08-26,google,1,7012,14565.0,14338.6666667
2017-08-27,google,1,7012,14580.0,14456.6666667
2017-08-28,google,1,7012,14227.0,14457.3333333
2017-08-29,google,1,7012,14568.0,14458.3333333
2017-08-30,google,1,7012,14582.0,14459.0
2017-08-31,google,1,7012,14214.0,14454.6666667
2017-09-01,google,1,7012,14053.0,14283.0

现在这种方法的问题是hits 的当前值包含在移动平均线中。

以 2017-09-01 为例。我需要 hits_avg 的值是 (14568+14582+14214)/3 = 14454.6 但我得到的是 (14582+14214+14053)/3 = 14283.0

如何让移动平均线取 3 天的值?

【问题讨论】:

  • 看看有没有它的功能。如果不是,可以使用 shift()?

标签: python pandas moving-average


【解决方案1】:

尝试添加 shift() 将比较窗口移动一步:

df_sorted['mov_av_hits'] = df_grouped_sorted[['hits']].shift().rolling(3, min_periods=3).mean().fillna(0).reset_index(
    0, drop=True)

我明白了:

         date    site  iso    id     hits   mov_av_hits
0  2017-08-25  google    1  7012  14225.0      0.000000
1  2017-08-26  google    1  7012  14565.0      0.000000
2  2017-08-27  google    1  7012  14580.0      0.000000
3  2017-08-28  google    1  7012  14227.0  14456.666667
4  2017-08-29  google    1  7012  14568.0  14457.333333
5  2017-08-30  google    1  7012  14582.0  14458.333333
6  2017-08-31  google    1  7012  14214.0  14459.000000
7  2017-09-01  google    1  7012  14053.0  14454.666667

【讨论】:

  • 这可行,但是当“站点”/“iso”更改时,它会导致 NaN。你能检查更新的样本数据吗?
  • @Craig 抱歉,我不在。很高兴你得到帮助!
【解决方案2】:

你可以试试这个..

df.hits.shift().rolling(3,min_periods=1).mean().fillna(df.hits)
Out[692]: 
0    14225.000000
1    14225.000000
2    14395.000000
3    14456.666667
4    14457.333333
5    14458.333333
6    14459.000000
7    14454.666667
Name: hits, dtype: float64

更新

df['new']=df.groupby('site').hits.apply(lambda x : x.shift().rolling(3,min_periods=1).mean().fillna(x))


df
Out[712]: 
          date      site  iso    id     hits           new
0   2017-08-25    google    1  7012  14225.0  14225.000000
1   2017-08-26    google    1  7012  14565.0  14225.000000
2   2017-08-27    google    1  7012  14580.0  14395.000000
3   2017-08-28    google    1  7012  14227.0  14456.666667
4   2017-08-29    google    1  7012  14568.0  14457.333333
5   2017-08-30    google    1  7012  14582.0  14458.333333
6   2017-08-31    google    1  7012  14214.0  14459.000000
7   2017-09-01    google    1  7012  14053.0  14454.666667
8   2017-08-25  facebook    2  7019  21225.0  21225.000000
9   2017-08-26  facebook    2  7019  21565.0  21225.000000
10  2017-08-27  facebook    2  7019  31580.0  21395.000000
11  2017-08-28  facebook    2  7019  13227.0  24790.000000
12  2017-08-29  facebook    2  7019  22568.0  22124.000000
13  2017-08-30  facebook    2  7019  44582.0  22458.333333
14  2017-08-31  facebook    2  7019  32214.0  26792.333333
15  2017-09-01  facebook    2  7019  44053.0  33121.333333

【讨论】:

  • 谢谢 Wen,但现在的问题是,当 siteiso 发生变化时,新 site/iso 的移动平均线的初始值包括来自以前的site/iso
  • @Craig 你只需要 groupby df.groupby('site').apply(lambda x : x.hits.shift().rolling(3,min_periods=1).mean().fillna(x.hits))
  • 如何将其分配回数据框?这作为一个独立的语句工作,但我想要 df 中新列中的值。尝试分配给新列会导致 TypeError: incompatible index of inserted column with frame index
  • @Craig df['new']=df.groupby('site').hits.apply(lambda x : x.shift().rolling(3,min_periods=1).mean().fillna(x)),这是分配回来
  • @Craig yw~ :-) 快乐编码
【解决方案3】:

这是一个解决方案,您可以一次计算多个不同的移动平均线:

df = df.assign(
    avg_hits_3=df_sorted.groupby('site')['hits'].rolling(3).mean().shift().values,
    avg_hits_5=df_sorted.groupby('site')['hits'].rolling(5).mean().shift().values,
    avg_hits_10=df_sorted.groupby('site')['hits'].rolling(10).mean().shift().values
)

【讨论】:

    猜你喜欢
    • 2020-08-21
    • 2019-06-10
    • 1970-01-01
    • 2017-09-21
    • 2021-05-15
    • 2020-10-23
    • 1970-01-01
    • 2019-03-24
    • 2021-02-08
    相关资源
    最近更新 更多