我有一个data.table
(dt_1
),其中包含2列(Observed_A
和Observed_B
)的测量值。我需要使用这些列中的值,并在分别引用列data.table
和dt_2
的样式为Modeled_A
(Modeled_B
)的第二次查找中查找最接近两个列的值。最终目标是,使用dt_2
中最匹配的行,在dt_2
(Variable_1
,Variable_2
和{{ 1}})并将其添加到Variable_3
中。
我希望使用dt_1
的{{1}}函数,因为我的实际data.table
很大(roll
; 30列和35000行)({{1} }; 17列和15,000行),但我不确定如何同时使用2列来完成此操作。
以下是一些示例数据:
data.tables
dt_1
注意:我通常不会发布这么长的示例(dt_2
),但我认为问题的本质是有根据的。
答案 0 :(得分:2)
答案的执行时间比较
library(ggplot2)
library(dplyr)
library(data.table)
library(microbenchmark)
mbm <- microbenchmark::microbenchmark(
dplyr = dt_2 %>%
slice(
apply(dt_1[,-1], 1, function(x) {
(abs(x[1] - dt_2$Modeled_A) + abs(x[2] - dt_2$Modeled_B)) %>%
which.min()
})
) %>%
mutate(id = as.character(1:nrow(.))) %>%
inner_join(dt_1, ., by = "id"),
data.table = dt_1[, c(.SD, dt_2[which.min(abs(Observed_A-Modeled_A) + abs(Observed_B-Modeled_B))]),
by=dt_2[, seq_len(.N)]],
data.table.reference = dt_1[, names(dt_2) := dt_2[which.min(abs(Observed_A-Modeled_A) + abs(Observed_B-Modeled_B))],
by=dt_1[, seq_len(.N)]])
autoplot(mbm)
实际数据的执行时间
我将其包括在内是为了显示较大数据表的性能差异,其中dt_1
由约35,000行30列组成,而dt_2
由约15,000行和17列组成。
答案 1 :(得分:1)
我不擅长data.table
,但这是一种tidyverse
可能会帮助您的方式-
dt_1 %>%
tibble::rownames_to_column("id") %>%
mutate(cj = 1) %>%
inner_join(dt_2 %>% mutate(cj = 1), by = "cj") %>%
select(-cj) %>%
mutate(
closeness = abs(Observed_A - Modeled_A) + abs(Observed_B - Modeled_B),
# closeness = 0 means perfect match
) %>%
arrange(id, closeness) %>%
group_by(id) %>%
slice(1) %>%
ungroup()
# A tibble: 8 x 9
id Observed_A Observed_B Modeled_A Modeled_B Variable_1 Variable_2 Variable_3 closeness
<chr> <dbl> <dbl> <dbl> <dbl> <int> <int> <int> <dbl>
1 1 - 9.70 -3.10 - 9.80 -2.80 4 448 251 0.400
2 2 -10.8 -5.20 -11.4 -5.90 80 865 63 1.30
3 3 - 9.70 -4.50 - 9.80 -4.30 37 857 281 0.300
4 4 - 9.20 -4.10 - 9.80 -4.30 37 857 281 0.800
5 5 - 9.50 -3.00 - 9.80 -2.80 4 448 251 0.500
6 6 -10.1 -2.70 - 9.80 -2.80 4 448 251 0.400
7 7 - 8.30 -2.60 - 8.20 -2.80 86 885 246 0.300
8 8 - 7.60 -2.60 - 8.20 -2.80 86 885 246 0.800
编辑:此方法避免了交叉联接,因此不应有内存问题。看看这是否足够快。无论哪种方式,我认为data.table
都应该更快。
dt_1 <- dt_1 %>%
tibble::rownames_to_column("id")
dt_2 %>%
slice(
apply(dt_1[,-1], 1, function(x) {
(abs(x[1] - dt_2$Modeled_A) + abs(x[2] - dt_2$Modeled_B)) %>%
which.min()
})
) %>%
mutate(id = as.character(1:nrow(.))) %>%
inner_join(dt_1, ., by = "id")
id Observed_A Observed_B Modeled_A Modeled_B Variable_1 Variable_2 Variable_3
1 1 -9.7 -3.1 -9.8 -2.8 4 448 251
2 2 -10.8 -5.2 -11.4 -5.9 80 865 63
3 3 -9.7 -4.5 -9.8 -4.3 37 857 281
4 4 -9.2 -4.1 -9.8 -4.3 37 857 281
5 5 -9.5 -3.0 -9.8 -2.8 4 448 251
6 6 -10.1 -2.7 -9.8 -2.8 4 448 251
7 7 -8.3 -2.6 -8.2 -2.8 86 885 246
8 8 -7.6 -2.6 -8.2 -2.8 86 885 246
答案 2 :(得分:1)
使用与Shree相同的距离量度,但在data.table中使用(虽然不要以为会更快):
library(data.table)
setDT(dt_1)
setDT(dt_2)
dt_1[, c(.SD, dt_2[which.min(abs(Observed_A-Modeled_A) + abs(Observed_B-Modeled_B))]),
by=dt_1[, seq_len(.N)]]
输出:
dt_1 Observed_A Observed_B Modeled_A Modeled_B Variable_1 Variable_2 Variable_3
1: 1 -9.7 -3.1 -9.8 -2.8 4 448 251
2: 2 -10.8 -5.2 -11.4 -5.9 80 865 63
3: 3 -9.7 -4.5 -9.8 -4.3 37 857 281
4: 4 -9.2 -4.1 -9.8 -4.3 37 857 281
5: 5 -9.5 -3.0 -9.8 -2.8 4 448 251
6: 6 -10.1 -2.7 -9.8 -2.8 4 448 251
7: 7 -8.3 -2.6 -8.2 -2.8 86 885 246
8: 8 -7.6 -2.6 -8.2 -2.8 86 885 246
编辑: 速度差异可能是由于列数很大。使用引用更新的另一种可能性:
library(data.table)
setDT(dt_1)
setDT(dt_2)
dt_1[, names(dt_2) := dt_2[which.min(abs(Observed_A-Modeled_A) + abs(Observed_B-Modeled_B))]),
by=dt_1[, seq_len(.N)]]
或者如果dt_1和dt_2都是矩阵,则使用基数R可能会更快。