我想计算每个15天的滚动平均值(前后)。这是一个测试框架:
date_list = seq(ymd('2000-01-15'),ymd('2010-09-18'),by='day')
testframe = data.frame(Date = date_list)
testframe$Day = substr(testframe$Date, start = 6, stop = 10)
testframe$V1 = runif(3900, 2.0, 35.0)
testframe$V2 = runif(3900, 5.0, 40.0)
testframe$V3 = runif(3900, -10.0, 10.0)
testframe$V4 = seq(from = 5, to = 45, length.out = 3900)
我知道如何为每列计算:
library(zoo)
rollmean(testframe$V4, 31)
rollapply(testframe$V4, 31, mean)
但是如何一次为每一列执行此操作?我认为我必须为此排除“日期和日期”列,但是如何在命令中执行此操作?在前15天和最后15天如何在带有NA的旧测试框架中获得结果?
我尝试过:
testframe[paste0("new_col",1:4)] <- lapply(testframe[,3:6], rollapply, FUN = mean, width = 31)
但这不起作用!
答案 0 :(得分:2)
rollmean和rollapply的默认操作是对每一列进行操作。请查看?rollapply
。
library(zoo)
rollmeanr(BOD, 2, fill = NA)
给出以下内容,其中rollmean应用于内置BOD的每一列:
Time demand
[1,] NA NA
[2,] 1.5 9.30
[3,] 2.5 14.65
[4,] 3.5 17.50
[5,] 4.5 15.80
[6,] 6.0 17.70
如果您只想将均值应用于某些列,请指定:
if (exists("BOD", .GlobalEnv)) rm(BOD)
BOD[1:2] <- rollmeanr(BOD[1:2], 2, fill = NA)
请注意,如果您拥有除索引列以外的所有数字列,那么仅使用Zoo对象而不是尝试将所有内容强制放入data.frame会更容易,因为在时间序列上效果不佳。
if (exists("BOD", .GlobalEnv)) rm(BOD)
z <- read.zoo(BOD)
rollmeanr(z, 2)
答案 1 :(得分:1)
虽然@ G.Grothendieck的回答在许多方面都比较好,但以下情况可能会导致您的情况出问题:
testframe[paste0("new_col",1:4)] <- lapply(testframe[,3:6], rollapply, FUN = mean, width = 31)
# Error in mean.default(X[[i]], ...) : 'trim' must be numeric of length one
这部分是因为您要传递FUN=
,但这也是lapply
的参数名称,因此在此有效地使用了它:
testframe[paste0("new_col",1:4)] <- lapply(testframe[,3:6], function(a) mean(a, trim=rollapply, width = 31))
mean
的第二个参数是trim=
,在这种情况下正在传递函数rollapply
,显然是不正确的。
下一步将是
testframe[paste0("new_col",1:4)] <- lapply(testframe[,3:6], function(a) rollapply(a, FUN = mean, width = 31))
# Error in `[<-.data.frame`(`*tmp*`, paste0("new_col", 1:4), value = list( :
# replacement element 1 has 3870 rows, need 3900
这是因为单个rollapply
不会返回前15个值(最后30个观察值)。您可以使用fill=NA
来解决此问题:
testframe[paste0("new_col",1:4)] <- lapply(testframe[,3:6], function(a) rollapply(a, FUN = mean, width = 31, fill = NA))
# (no warnings/errors)