R 从较大的“查找”样式data.table中查找最接近的2列值
我有一个data.table dt_1,其中包含观察到的两列和观察到的两列的测量值。我需要使用这些列中的值,并在第二个查找样式的data.table dt_2中查找与这两列最近的值。table dt_2分别引用建模的列和建模的列。最终目标是,使用dt_2中最接近匹配的行,选择dt_2变量_1、变量_2和变量_3中的3个附加建模列值,并将它们添加到dt_1中 我希望使用data.table的roll函数作为我的实际数据;30列和35000行dt_2;17列和15000行,但我不确定如何用2列同时完成这一任务 以下是一些示例数据:R 从较大的“查找”样式data.table中查找最接近的2列值,r,data.table,lookup,closest,R,Data.table,Lookup,Closest,我有一个data.table dt_1,其中包含观察到的两列和观察到的两列的测量值。我需要使用这些列中的值,并在第二个查找样式的data.table dt_2中查找与这两列最近的值。table dt_2分别引用建模的列和建模的列。最终目标是,使用dt_2中最接近匹配的行,选择dt_2变量_1、变量_2和变量_3中的3个附加建模列值,并将它们添加到dt_1中 我希望使用data.table的roll函数作为我的实际数据;30列和35000行dt_2;17列和15000行,但我不确定如何用2列同时完
dt_1 <- structure(list(Observed_A = c(-9.7, -10.8, -9.7, -9.2, -9.5,
-10.1, -8.3, -7.6), Observed_B = c(-3.1, -5.2, -4.5, -4.1, -3,
-2.7, -2.6, -2.6)), class = "data.frame", row.names = c(NA, -8L))
注意:我通常不会发布这么长的dt_2示例,但我认为问题的本质证明了这一点。我不擅长data.table,但这里有一个小方法可以帮助您-
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 %>%
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
使用与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可能更快。使用与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可能更快。比较答案的执行时间
实际数据的执行时间
我包含这一点是为了显示较大数据表的性能差异,其中dtu 1由约35000行30列组成,dtu 2由约15000行17列组成
比较答案的执行时间
实际数据的执行时间
我包含这一点是为了显示较大数据表的性能差异,其中dtu 1由约35000行30列组成,dtu 2由约15000行17列组成
你的答案很有用。我不接受它的唯一原因是因为我需要使用data.table,因为我的实际dt_1包含超过35000个观察值和30个变量,而我的实际dt_2包含超过15000个观察值和17个变量。我在上面尝试了你的代码,但由于dplyr占用内存的特性,内存耗尽了16 gb。我认为交叉连接可能是内存方面的主要原因。它创建了35000*15000 525MM行和47列,这当然很大。我来看看是否有办法避免交叉连接。这样效果更好!好奇的是,如果我观察到第三个测量列,第三个建模列,我会在代码中添加sliceapplydt_1[,-1],1,functionx{absx[1]-dt_2$modeled_a+absx[2]-dt_2$modeled_B+absx[3]-dt_2$modeled_C%>%which.min}太棒了。再次感谢。你的回答很有效。我不接受它的唯一原因是因为我需要使用data.table,因为我的实际dt_1包含超过35000个观察值和30个变量,而我的实际dt_2包含超过15000个观察值和17个变量。我在上面尝试了你的代码,但由于dplyr占用内存的特性,内存耗尽了16 gb。我认为交叉连接可能是内存方面的主要原因。它创建了35000*15000 525MM行和47列,这当然很大。我来看看是否有办法避免交叉连接。这样效果更好!好奇的是,如果我观察到第三个测量列,第三个建模列,我会在代码中添加sliceapplydt_1[,-1],1,functionx{absx[1]-dt_2$modeled_a+absx[2]-dt_2$modeled_B+absx[3]-dt_2$modeled_C%>%which.min}太棒了。再次感谢。感谢@chinsoon12和@Shree,我做了一个快速的性能检查,看看哪种方法更有效。我必须发布一个答案,因为我的OP超过了字符限制。dplyr在执行时间上胜过data.table!您好@chinsoon12,我已经用您新的data.table引用版本data.table.reference更新了我的回复。看起来dplyr更快。另外,您的代码中还有一个额外的。这对我有效:dt_1[,名称dt_2:=dt_2[which.minabsObserved_A-Modeled_A+absObserved_B-Modeled_B],by=dt_1[,seq_len.N]]谢谢@chinsoon12和@Shree,我做了一个快速的性能检查,看看哪种方法更有效,因为我的OP超过了字符限制,我不得不发布一个答案。dplyr在执行时间上胜过data.table!您好@chinsoon12,我已经用您新的data.table引用版本data.table.reference更新了我的回复。看起来dplyr更快。另外,您的代码中还有一个额外的。这对我有效:dt_1[,名称dt_2:=dt_2[w
我有点惊讶。也许在这两个软件包中都有经验的人可以提供一些信息。我认为这是因为专栏的数量。我将尝试使用另一种索引方法,而不是.SD。之后,我有点惊讶。也许在这两个软件包中都有经验的人可以提供一些信息。我认为这是因为专栏的数量。稍后我将尝试使用另一种索引方法,而不是.SD