如何在数据帧的每个子组中找到移动平均值

时间:2019-08-05 05:44:23

标签: r dataframe moving-average

如果我具有以下数据框:

set.seed(21) 
df1 <- data.frame(col1=c(rep('a',5), rep('b',5), rep('c',5)), col4=rnorm(1:15))

   col1         col4 
1     a  0.793013171 
2     a  0.522251264 
3     a  1.746222241 
4     a -1.271336123 
5     a  2.197389533 
6     b  0.433130777 
7     b -1.570199630 
8     b -0.934905667 
9     b  0.063493345 
10    b -0.002393336 
11    c -2.276781240 
12    c  0.757412225 
13    c -0.548405554 
14    c  0.172549478 
15    c  0.562853068 

如何在每个组中得出2或3或4点的移动平均值?即

col1           col4 SMA 
   a    0.793013171 NA 
   a    0.522251264 0.657632218 
   a    1.746222241 1.134236753 
   a    -1.271336123    0.237443059 
   a    2.197389533 0.463026705 
   b    0.433130777 NA 
   b    -1.57019963 -0.568534427 
   b    -0.934905667    -1.252552649 
   b    0.063493345 -0.435706161 
   b    -0.002393336    0.030550005 
   c    -2.27678124 NA 
   c    0.757412225 -0.759684508 
   c    -0.548405554    0.104503336 
   c    0.172549478 -0.187928038 
   c    0.562853068 0.367701273

根据我的阅读,我认为这可能与以下内容类似:

aggregate(df1$col4, by=list(df1$col1), function(x) {filter(x, 
rep(1/2,2), sides=1 )} ) 
  

aggregate.data.frame(as.data.frame(x),...)中的错误:     “ FUN”必须始终返回标量

但这告诉我(我认为)聚合应该只返回一个 每组的价值。所以我想我需要的是所有东西 给定组中的值,并返回相同长度的向量。 不知道该使用哪个功能。

1 个答案:

答案 0 :(得分:1)

我们可以使用zoo::rollmeanr

使用基数R:

df1$SMA <- with(df1, ave(col4, col1, FUN = function(x) 
                zoo::rollmeanr(x, 2, fill = NA)))
df1
#   col1         col4        SMA
#1     a  0.793013171         NA
#2     a  0.522251264  0.6576322
#3     a  1.746222241  1.1342368
#4     a -1.271336123  0.2374431
#5     a  2.197389533  0.4630267
#6     b  0.433130777         NA
#7     b -1.570199630 -0.5685344
#8     b -0.934905667 -1.2525526
#9     b  0.063493345 -0.4357062
#10    b -0.002393336  0.0305500
#11    c -2.276781240         NA
#12    c  0.757412225 -0.7596845
#13    c -0.548405554  0.1045033
#14    c  0.172549478 -0.1879280
#15    c  0.562853068  0.3677013

使用dplyr

library(dplyr)

df1 %>%
  group_by(col1) %>%
  mutate(SMA = zoo::rollmeanr(col4, 2, fill = NA))

使用data.table

library(data.table)
setDT(df1)[, SMA := zoo::rollmeanr(col4, 2, fill = NA), by = col1]