【发布时间】:2018-03-01 04:23:16
【问题描述】:
考虑以下 data.table 事件:
library(data.table)
breaks <- data.table(id = 1:8,
Channel = c("NP1", "NP1", "NP2", "NP2", "NP3", "NP3", "AT4", "AT4"),
Time = c(1000, 1100, 975, 1075, 1010, 1080, 1000, 1050),
Day = c(1, 1, 1, 1, 1, 1, 1, 1),
ZA = c(15, 12, 4, 2, 1, 2, 23, 18),
stringsAsFactors = F)
breaks
id Channel Time Day ZA
1: 1 NP1 1000 1 15
2: 2 NP1 1100 1 12
3: 3 NP2 975 1 4
4: 4 NP2 1075 1 2
5: 5 NP3 1010 1 1
6: 6 NP3 1080 1 2
7: 7 AT4 1000 1 23
8: 8 AT4 1050 1 18
对于中断中的每个唯一事件,我想使用 Time 变量(其中 Day == Day)在所有其他频道中找到最近的事件,然后对这些事件的 ZA 值求和。
这是我想要达到的结果:
id Channel Time Day ZA Sum
1: 1 NP1 1000 1 15 28
2: 2 NP1 1100 1 12 22
3: 3 NP2 975 1 4 39
4: 4 NP2 1075 1 2 32
5: 5 NP3 1010 1 1 42
6: 6 NP3 1080 1 2 32
7: 7 AT4 1000 1 23 20
8: 8 AT4 1050 1 18 19
所以对于第一行,通道是 NP1。 Time = 1000 的所有其他频道中的关闭事件是第 3、5 和 7 行。4+1+23 = 28
我通过以下代码使用 data.table 使其工作:
breaks[breaks[, c("Day", "Time", "Channel", "ZA")], on = "Day", allow.cartesian = TRUE][
Channel != i.Channel][
order(id)][
, delta := abs(Time - i.Time)][
, .SD[delta == min(delta)], by = .(Channel, Time, Day, i.Channel)][
, unique(.SD, by = c("id", "i.Channel"))][
, .(Sum = sum(i.ZA)), by = .(id, Channel, Time, Day, ZA)]
但是,这会在第一步中创建一个包含 64 行的数据集,我想使用超过一百万行的数据集来执行此操作。
谁能帮我找到更有效的方法?
编辑:
我在包含 39 个不同通道的 140 万行的完整数据集上尝试了 G. Grothendieck (sqldf)、eddi (data.table) 和 MarkusN (dplyr) 的解决方案。数据集在内存中。
sqldf: 54 minutes
data.table: 11 hours
dplyr: 29 hours
【问题讨论】:
标签: r data.table sqldf