我有2个tibble数据框,我正在努力调和。第一个tibble有超过一百万个观测值,前几行如下:
data
ID Time(Converted to number)
1 23160
1 23161
1 23162
1 23163
1 23164
1 23165
2 24251
2 24252
第二个tibble是一个查找表(包含已发生的特定事件的信息),简化版本如下:
lookup_table
ID Event_Time Event_Indicator Number_of_Cumulative_Events
1 23162 1 1
1 23164 1 2
2 24255 1 1
2 24280 0 1
我想在第一个tibble中创建第3列,以便显示观察时的累积事件数。因此,上例中的第3列是:
ID Time(Converted to number) Number
1 23160 0
1 23161 0
1 23162 1
1 23163 1
1 23164 2
1 23165 2
2 24251 0
2 24252 0
由于计算时间的原因,我试图避免在数百万次观察中循环以将每个观察的时间与查找表中的Event_Time进行比较。
但是,我不知道如何在不使用循环的情况下这样做。问题是lookup_table多次包含一些ID,如果所有ID只出现在lookup_table中一次,那么我可以这样做:
data$Event_Time <- lookup_table[match(data$ID, lookup_table$ID),"Event_Time"]
data$Number <- data %>% mutate(ifelse(Time >= Event_Time,1,0))
我有什么想法可以避免使用循环并为每次观察应用查找条件?谢谢。
编辑:我不是要尝试连接表,而是更多地比较lookup_table和数据表中的时间列以获取我想要的列。例如,如果我要写一个低效的循环函数,那就是:
for (i in 1:nrow(data)) {
data$Number[i] <- subset(lookup_table,ID == data$ID[i])[max(which
(data$Time[i] >= lookup_table$Event_Time)), "Number_of_Cumulative_Events"]
}
答案 0 :(得分:2)
可能的解决方案是在加入后计算累积事件。请注意,使用更新连接。
library(data.table)
setDT(data)[, new := 0L][setDT(lookup_table), on = .(ID, Time = Event_Time), new := Event_Indicator][
, new := cumsum(new), by = ID][]
ID Time new 1: 1 23160 0 2: 1 23161 0 3: 1 23162 1 4: 1 23163 1 5: 1 23164 2 6: 1 23165 2 7: 2 24251 0 8: 2 24252 0
可替换地,
setDT(data)[setDT(lookup_table), on = .(ID, Time = Event_Time), new := Event_Indicator][
is.na(new), new := 0][
, new := cumsum(new), by = ID][]
将在连接后将缺失的条目设置为零。
完全不同的方法是使用滚动连接:
lookup_table[, !"Event_Indicator"][data, on = .(ID, Event_Time = Time), roll = TRUE]
ID Event_Time Number_of_Cumulative_Events 1: 1 23160 NA 2: 1 23161 NA 3: 1 23162 1 4: 1 23163 1 5: 1 23164 2 6: 1 23165 2 7: 2 24251 NA 8: 2 24252 NA
(NA
&#39}未被触及以供说明)