我有data.frame
列Date
列以及其他一些变量,例如:
df <- data.frame(date = rep(seq.Date(as.Date("2017-01-01"), as.Date("2017-01-10"), by = "day"), 2),
x = c(rep("a", 10), rep("b", 10)),
y = rep(letters[3:7], each = 4),
z = rnorm(20))
我希望在Date
上“滑动”,为某个宽度的每个“窗口”计算一些新的data.frame
(比如说所有3天的时间段),然后将它们绑定到一个新的data.frame
,比如用一段句子“标识符”来知道每一行来自哪个时期,例如这个时期的第一个日期。
示例,非常漂亮/慢速的方式:
windowLength <- 3
dateVec <- df$date %>% unique %>% unlist
nonTrivialFunctionWhichCreatesANewDataFrame <- function(i) {
df %>%
filter(date >= dateVec[i], date <= dateVec[i + windowLength - 1]) %>%
group_by(x, y) %>%
summarise(zSum = sum(z), zCount = n()) %>%
mutate(startDate = dateVec[i])
}
df2 <- NULL
for (i in 1:(length(dateVec) - windowLength + 1)) {
dfTemp <- nonTrivialFunctionWhichCreatesANewDataFrame(i)
df2 <- rbind(df2, dfTemp)
}
head(df2)
Source: local data frame [6 x 5]
Groups: x [2]
x y zSum zCount startDate
<fctr> <fctr> <dbl> <int> <date>
1 a c 1.27899229 3 2017-01-01
2 b e 1.05072378 2 2017-01-01
3 b f -1.04083228 1 2017-01-01
4 a c 0.67568894 3 2017-01-02
5 b e 0.03046459 1 2017-01-02
6 b f -1.55901277 2 2017-01-02
我尝试使用rollapply
包中的zoo
,首先将我的data.frame
定义为时间序列对象 - 但无济于事。
什么是更快,更无循环的方法呢?
更新:为什么zoo
的{{1}}对我不起作用
简单示例:
rollapply
正如您所看到的,因为日期不是唯一的,尽管z <- zoo(1:10, as.Date(rep(31:35, 2)))
z
1970-02-01 1970-02-01 1970-02-02 1970-02-02 1970-02-03 1970-02-03 1970-02-04 1970-02-04 1970-02-05
1 6 2 7 3 8 4 9 5
1970-02-05
10
rollapply(z, width = 3, FUN = sum, align = "right")
1970-02-02 1970-02-02 1970-02-03 1970-02-03 1970-02-04 1970-02-04 1970-02-05 1970-02-05
9 15 12 18 15 21 18 24
确认重新排列数据,但sum函数仅在3行上滚动(第1个元素为1 + 6 + 2 = 9) ) - 根据需要不在3 天!