例如,如果我有一个像这样的data.table:
timestamp A B C
1: 2014-10-04 00:00:00 0.77931331 0.56750899 0.1017191
2: 2014-10-04 02:10:54 0.79579910 0.37156058 0.9536724
3: 2014-10-04 04:21:49 0.12088298 0.50284511 0.1332756
4: 2014-10-04 06:32:43 0.21722767 0.29294422 0.9135702
5: 2014-10-04 08:43:38 0.50177676 0.01302987 0.4106962
6: 2014-10-04 10:54:32 0.44592820 0.59690143 0.8262488
7: 2014-10-04 13:05:27 0.36409504 0.60071189 0.6558466
8: 2014-10-04 15:16:21 0.36094231 0.90065483 0.2410778
9: 2014-10-04 17:27:16 0.16668868 0.02374610 0.7664427
10: 2014-10-04 19:38:10 0.29222104 0.47992082 0.6199720
11: 2014-10-04 21:49:05 0.08729134 0.08450253 0.1184836
12: 2014-10-05 00:00:00 0.24222748 0.67493498 0.5414503
和其他data.table,我需要在其中添加其他列,其中包含上面给出的特定时间戳和列名的值:
timestamp Class
1: 2014-10-04 00:00:00 A
2: 2014-10-04 04:21:49 A
3: 2014-10-04 08:43:38 A
4: 2014-10-04 10:54:32 B
5: 2014-10-04 15:16:21 B
6: 2014-10-04 21:49:05 C
其中应如下所示:
timestamp class value
1: 2014-10-04 00:00:00 A 0.77931331
2: 2014-10-04 04:21:49 A 0.12088298
3: 2014-10-04 08:43:38 A 0.50177676
4: 2014-10-04 10:54:32 B 0.59690143
5: 2014-10-04 15:16:21 B 0.90065483
6: 2014-10-04 21:49:05 C 0.11848360
实际上,我的表很长(最多100,000行),当我实现这样的算法时,运行时间很长:
class.values <- sapply(1:nrow(dt2), function (row) {
timestamp.tmp <- dt2[row,timestamp]
class.name <- d2[row,class]
dt1[timestamp == timestamp.tmp,get(class.name)]
})
dt2[,value := class.values]
这是生成数据的额外代码:
library(data.table)
timestamps <- seq(as.POSIXct("2014-10-04"),as.POSIXct("2014-10-05"),length.out = 12)
dt1 <- data.table(
timestamp = timestamps,
A = runif(12),
B = runif(12),
C = runif(12)
)
dt2 <- data.table(
timestamp = sort(sample(timestamps,6)),
class = c("A","A","A","B","B","C")
)
答案 0 :(得分:1)
我们可以试试吗?首先使用dt1
将gather
转置为长格式;然后按时间戳和类别与dt2
右联接(查找值)。不知道下面的代码是否适合您的大数据。但可以尝试一下。
library(dplyr)
dt1 %>%
gather(key = class, value = value, 2:4) %>%
right_join(dt2, by = c('timestamp', 'class'))
timestamp class value
1 2014-10-04 02:10:54 A 0.6719328
2 2014-10-04 04:21:49 A 0.4344919
3 2014-10-04 06:32:43 A 0.8979173
4 2014-10-04 08:43:38 B 0.2372619
5 2014-10-04 19:38:10 B 0.6164465
6 2014-10-05 00:00:00 C 0.1237939
答案 1 :(得分:1)
dt1_long = melt(dt1, id.vars = "timestamp", variable.name = "class")
merge(dt2, dt1_long, by = c("timestamp", "class"))
# timestamp class value
# 1: 2014-10-04 04:21:49 A 0.7966793
# 2: 2014-10-04 06:32:43 A 0.6767318
# 3: 2014-10-04 08:43:38 A 0.4939699
# 4: 2014-10-04 15:16:21 B 0.5750648
# 5: 2014-10-04 17:27:16 B 0.5254984
# 6: 2014-10-04 19:38:10 C 0.2108290
这与liuminzhao的回答相同,但是我们使用data.table::melt
代替tidyr::gather
,并且使用data.table::merge
代替dplyr::right_join
,因此速度非常快。
答案 2 :(得分:1)
对于base R
,一个选项是match
,具有行/列索引
m1 <- cbind(match(dt2$timestamp, dt1$timestamp), match(dt2$class, names(dt1)[-1]))
dt2$value <- as.data.frame(dt1)[,-1][m1]
dt2
# timestamp class value
#1: 2014-10-04 04:21:49 A 0.8299307
#2: 2014-10-04 08:43:38 A 0.7241582
#3: 2014-10-04 10:54:32 A 0.8822673
#4: 2014-10-04 13:05:27 B 0.7756672
#5: 2014-10-04 15:16:21 B 0.7656326
#6: 2014-10-04 17:27:16 C 0.9208442
注意:未设置seed
,因此值将不同