【问题标题】:Rolling average indexed on multiple variables基于多个变量的滚动平均值
【发布时间】:2021-06-21 00:35:45
【问题描述】:

我正在使用一个数据框,该数据框按三个变量(日期、活动和国家/地区)对值进行索引。其他每个值都根据这三个值进行索引,如下所示:

# Groups:   date, campaign [1,325]
   date          campaign country  cost clicks
   <date>           <dbl> <chr>   <dbl>  <dbl>
 1 2021-03-01 10127671839 0        0.45    7
 2 2021-03-01 10127671839 AD       0.47    10
 3 2021-03-01 10127671839 AE       0.39    11
 4 2021-03-01 10127671839 AF       0.27    2
 5 2021-03-01 10127671839 AG          0    0
 6 2021-03-01 10127671839 AI       1.28    2
 7 2021-03-01 10127671839 AL       0.66    6
 8 2021-03-01 10127671839 AM       0.33    2 
 9 2021-03-01 10127671839 AO          0    0
10 2021-03-01 10127671839 AR          0    0
# … with 335,215 more rows

我正在尝试创建这些值的移动平均值(在上表中,“成本”和“点击次数”)仍然按国家、广告系列和日期编制索引。

编辑:我找到了一个很好的函数,当只有两个索引变量时可以工作(在这里:Rolling mean (moving average) by group/id with dplyr),但我没有足够的技能来调整代码来处理三个或更多变量。

【问题讨论】:

  • df %&gt;% group_by(date, campaign, country) %&gt;% mutate(across(c(cost,clicks), list(rm = ~ zoo::rollmean(., 2, fill=NA))))

标签: r database dataframe dplyr tidyverse


【解决方案1】:

我认为zoo::rollmean 在这里效果很好,dplyr::group_by 可以根据需要处理任意数量的索引变量:

library(dplyr)
mtcars %>%
  group_by(cyl, am, vs) %>%
  mutate(across(c(mpg,disp), list(rm = ~ zoo::rollmeanr(., 2, fill = NA))))
# # A tibble: 32 x 13
# # Groups:   cyl, am, vs [7]
#      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb mpg_rm disp_rm
#    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>   <dbl>
#  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4   NA       NA 
#  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4   21      160 
#  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1   NA       NA 
#  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1   NA       NA 
#  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2   NA       NA 
#  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1   19.8    242.
#  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4   16.5    360 
#  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2   NA       NA 
#  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2   23.6    144.
# 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4   18.6    196.
# # ... with 22 more rows

fill=NA 参数意味着每个系列中的第一个没有历史可以平均,所以它是NA。如果您希望系列中的第一个是其自身的平均值,您可以改用partial=TRUE(改用rollapplyr):

mtcars %>%
  group_by(cyl, am, vs) %>%
  mutate(across(c(mpg,disp), list(rm = ~ zoo::rollapplyr(., 2, FUN = mean, partial = TRUE))))
# # A tibble: 32 x 13
# # Groups:   cyl, am, vs [7]
#      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb mpg_rm disp_rm
#    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>   <dbl>
#  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4   21      160 
#  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4   21      160 
#  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1   22.8    108 
#  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1   21.4    258 
#  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2   18.7    360 
#  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1   19.8    242.
#  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4   16.5    360 
#  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2   24.4    147.
#  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2   23.6    144.
# 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4   18.6    196.
# # ... with 22 more rows

我使用了 zoo 函数的 align="right" 变体,假设您的移动平均值是历史的,并且时间在后续行中增加。如果这些假设不正确,请确保您有意在 align-variants 之间进行选择。

我在这里使用dplyr::across 一步处理任意数量的列:由于我使用了“波浪号函数”的命名列表,因此它获取每个函数的名称并将其附加到每个函数的名称中列名。如果您愿意,可以将其分解为单独的 mutate 分配,以提高可读性、可维护性,或者如果您需要为每列设置不同的参数集。

【讨论】:

  • 我试过你的代码,但由于某种原因它只返回 NA,或者,如果我使用第二个代码(部分 = TRUE)它只返回与以前相同的数字。顺便说一句,我正在使用 n = 7。你知道这会是什么问题吗?
  • 这是代码:db = db %>% group_by(date, campaign, country) %>% mutate(across(c(clicks,cost), list(mav = ~ rollmeanr(., 7、填充=NA))))
  • 没关系,一旦我更改了行名以根据日期将它们按顺序排列,并从 group_by 函数中删除日期,我设法修复它
  • 很高兴你找到了它。我承认我对按日期分组持怀疑态度,而是认为你会想要dat %&gt;% arrange(date) %&gt;% group_by(a, b) ...。
猜你喜欢
  • 2021-02-10
  • 1970-01-01
  • 1970-01-01
  • 2015-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-11
  • 2012-02-14
相关资源
最近更新 更多