我有一个数据集,其中包含在给定日期的特定时间发生的10个事件,并且每个事件都有相应的值:
d1 <- data.frame(date = as.POSIXct(c("21/05/2010 19:59:37", "21/05/2010 08:40:30",
"21/05/2010 09:21:00", "21/05/2010 22:29:50", "21/05/2010 11:27:34",
"21/05/2010 18:25:14", "21/05/2010 15:16:01", "21/05/2010 09:41:53",
"21/05/2010 15:01:29", "21/05/2010 09:02:06"), format ="%d/%m/%Y %H:%M:%S"),
value = c(11313,42423,64645,643426,1313313,1313,3535,6476,11313,9875))
我希望每3分钟汇总一次结果,以标准的数据框格式呈现(从“2010年5月21日 00:00:00”到“2010年5月21日 23:57:00”,使数据框具有480个3分钟的bin)。
首先,我创建一个数据框,其中包含每个3分钟的bin:
d2 <- data.frame(date = seq(as.POSIXct("2010-05-21 00:00:00"),
by="3 min", length.out=(1440/3)))
然后,我将这两个数据框合并在一起,并删除NA值:
library(dplyr)
m <- merge(d1, d2, all=TRUE) %>% mutate(value = ifelse(is.na(value),0,value))
最后,我使用来自xts
包的period.apply()
函数对每个“bin”中的值求和:
library(xts)
a <- period.apply(m$value, endpoints(m$date, "minutes", 3), sum)
有没有更有效的方法来完成这个任务?它感觉不够优化。
更新 #1
在 Joshua 的回答后,我调整了我的代码:
library(xts)
startpoints <- function (x, on = "months", k = 1) {
head(endpoints(x, on, k) + 1, -1)
}
m <- seq(as.POSIXct("2010-05-21 00:00:00"), by="3 min", length.out=1440/3)
x <- merge(value=xts(d1$value, d1$date), xts(,m))
y <- period.apply(x, c(0,startpoints(x, "minutes", 3)), sum, na.rm=TRUE)
我之前不知道period.apply()
可以使用na.rm=TRUE
,现在可以跳过mutate(value = ifelse(is.na(value),0,value))
。这是一步向前迈进,我很满意这里的xts
方法,但我想知道是否有一个纯粹的dplyr
解决方案可以在这种情况下使用。
更新#2
在尝试Khashaa的答案后,我因为没有指定时区而出现错误。所以我有:
> tail(d4)
interval sumvalue
476 2010-05-21 23:45:00 NA
477 2010-05-21 23:48:00 NA
478 2010-05-21 23:51:00 NA
479 2010-05-21 23:54:00 NA
480 2010-05-21 23:57:00 11313
481 2010-05-22 02:27:00 643426
> d4[450,]
interval sumvalue
450 2010-05-21 22:27:00 NA
现在,在执行Sys.setenv(TZ="UTC")
之后,所有问题都已解决。
as.POSIXct
但没有指定时区,因此它会使用您的本地时区;而 Khashaa 使用的是lubridate::ymd_hms
,如果您不指定时区,它会默认使用UTC
时区。如果您在运行定义d1
的代码之前调用Sys.setenv(TZ="UTC")
,则会得到与 Khashaa 相同的结果。请注意,这里不能进行解释或返回任何其他内容。 - GSee