【发布时间】:2015-08-05 09:01:56
【问题描述】:
我经常必须在给定的时间间隔(“事件”)内平均时间序列数据,基本上就像here 所问的那样。
正如答案中所建议的,我以“长”格式对我的数据使用 SQL 语句。这是一个例子:
#create dummy data frame
set.seed(1)
data <- data.frame(
date = seq(from = as.POSIXct("2014-01-01 00:00"),
to = as.POSIXct("2014-01-31 23:00"),
by = 300),
A = runif(8917),
B = runif(8917),
C = runif(8917),
D = runif(8917)
)
#convert to long format
require(dplyr)
data <- data %>%
gather(class,value,A:D)
# create dummy events
events <- data.frame(
id = c("blue","red","green","yellow"),
start = as.POSIXct(c("2014-01-03 13:00",
"2014-01-12 08:00",
"2014-01-18 10:00",
"2014-01-27 23:00")),
stop = as.POSIXct(c("2014-01-03 19:00",
"2014-01-13 17:00",
"2014-01-20 10:00",
"2014-01-28 20:00"))
)
#average value within events, grouped by class
require(sqldf)
results <- sqldf("
SELECT x.id, y.class, avg(y.value) AS mean
FROM events as x, data as y
WHERE y.date between x.start and x.stop
GROUP BY x.id, y.class
")
给出所需的输出
id class mean
1 blue A 0.4879129
2 blue B 0.4945888
3 blue C 0.5312504
4 blue D 0.4968260
5 green A 0.5235671
6 green B 0.5030602
7 green C 0.5071219
8 green D 0.5002010
9 red A 0.5122966
10 red B 0.4767966
11 red C 0.5032387
12 red D 0.5018389
13 yellow A 0.4727868
14 yellow B 0.4626688
15 yellow C 0.4930207
16 yellow D 0.5184966
但是,由于我的真实数据很大(长格式可以达到几百万行),SQL操作需要相当长的时间。
是否有更有效的方法来执行此操作?我偶然发现了data.table::foverlaps,它被称为“重叠连接”,但我不完全明白这是否是我需要的。
如果有一种有效的方法可以将 en 'event' 列添加到数据中,指示每一行(日期),它属于哪个事件,那么我可以使用 dplyr 进行分组汇总,并与 SQL 语句进行比较。但我不知道该怎么做......
如果专家提出任何建议,我们将不胜感激。
更新
按照 cmets 中的建议,我已将索引的创建添加到我的 SQL 语句中。不幸的是,这并没有加快我在现实世界中的一个大问题的速度。计算仍然需要大约 40 分钟才能运行。
然后,我复制粘贴了由 David 提供的 data.table 解决方案,令人印象深刻的是,它在完全相同的真实数据集上运行时间不到 1 秒。
我仍然不明白它是如何以及为什么这样做的,但是我花一些时间学习 data.table 语法的动力确实增加了很多。再次感谢!
【问题讨论】:
-
您是否尝试过使用
data.table::foverlaps?您可以查看其文档或搜索 SO。有许多类似的 Q/A 说明了如何在不同情况下使用它。 -
你看过
?foverlaps吗?如果是这样,你不明白什么? -
我确实看过它,但我没有尝试使用它,因为我不确定它是否是我需要的。老实说,我对data.table语法有点害怕,我对编码不是很有经验……但如果这是我需要的功能,那么我会尝试理解它。谢谢。
-
如果你被吓倒了,你可能应该坚持使用 dplyr / SQL。祝你好运!
-
尝试添加索引:
sqldf(c("CREATE INDEX a1 ON data(class, value)", "SELECT x.id, y.class, avg(y.value) AS mean FROM events as x, main.data as y WHERE y.date between x.start and x.stop GROUP BY x.id, y.class "))
标签: r data.table dplyr