我需要为每个ID.y(形成唯一对)选择一个唯一的ID.x,以从最小的距离值开始最小化距离值。我觉得这有点像数独难题,因为每个x和y只能使用一次,因此每对的信息都可以匹配其他对。
在下面的示例中,ID.x 55与ID.x 56的匹配更好,因为ID.x 56与ID.y 2的匹配更好。类似地,ID.x 58可以与ID.y 4匹配,因为任何其他可用选项都将具有更大的距离,然后ID.y 5可以在距离4处获得ID.x59。但是,ID.y 7无法匹配,因为ID.x 61和ID.x 62同样接近。
示例:
DT = data.table(
ID.x = c("55", "55", "55", "55", "55", "55", "55", "56", "56", "56", "56", "56", "56", "56", "57", "57", "57", "57", "57", "57", "57", "58", "58", "58", "58", "58", "58", "58", "59", "59", "59", "59", "59", "59", "59", "60", "60", "60", "60", "60", "60", "60", "61", "61", "61", "61", "61", "61", "61", "62", "62", "62", "62", "62", "62", "62"),
ID.y = c("1", "2", "3", "4", "5", "6", "7", "1", "2", "3", "4", "5", "6", "7", "1", "2", "3", "4", "5", "6", "7", "1", "2", "3", "4", "5", "6", "7", "1", "2", "3", "4", "5", "6", "7", "1", "2", "3", "4", "5", "6", "7", "1", "2", "3", "4", "5", "6", "7", "1", "2", "3", "4", "5", "6", "7"),
distance = c("2", "3", "3", "4", "6", "6", "7", "2", "1", "2", "5", "5", "5", "6", "4", "4", "3", "5", "5", "5", "6", "5", "5", "5", "4", "4", "5", "6", "7", "7", "7", "6", "4", "6", "7", "6", "6", "6", "6", "4", "2", "5", "7", "7", "7", "7", "5", "5", "5", "6", "6", "6", "6", "4", "4", "5")
)
目标:
ID.x ID.y distance
1: 55 1 2
2: 56 2 1
3: 57 3 3
4: 58 4 4
5: 59 5 4
6: 60 6 2
7: NA 7 NA
第一次尝试inspired by this question无效:
DT[DT[, .I[distance == min(distance)], by=ID.x]$V1][DT[, .I[1], by = ID.y]$V1]
更新: 为了响应@ chinsoon12和@paweł-chabros的回答,以下是更新的data.table,该表修复了一些问题。它交换x和y(我最初的问题是将x与y匹配,但更自然的解释是将x与y匹配)。本示例删除了ID.y 7的歧义匹配。在本示例中,最小距离匹配ID.x63。另外,我还添加了一个新的ID.y 8,以阐明何时不可能进行明确匹配(它匹配ID。 x 64和65也一样)。答案不应随意选择匹配项。
DT = data.table(
ID.y = c("55", "55", "55", "55", "55", "55", "55", "55", "56", "56", "56", "56", "56", "56", "56", "56", "57", "57", "57", "57", "57", "57", "57", "57", "58", "58", "58", "58", "58", "58", "58", "58", "59", "59", "59", "59", "59", "59", "59", "59", "60", "60", "60", "60", "60", "60", "60", "60", "61", "61", "61", "61", "61", "61", "61", "61", "62", "62", "62", "62", "62", "62", "62", "62", "63", "63", "63", "63", "63", "63", "63", "63", "64", "64", "64", "64", "64", "64", "64", "64", "65", "65", "65", "65", "65", "65", "65", "65"),
ID.x = c("1", "2", "3", "4", "5", "6", "7", "8", "1", "2", "3", "4", "5", "6", "7", "8", "1", "2", "3", "4", "5", "6", "7", "8", "1", "2", "3", "4", "5", "6", "7", "8", "1", "2", "3", "4", "5", "6", "7", "8", "1", "2", "3", "4", "5", "6", "7", "8", "1", "2", "3", "4", "5", "6", "7", "8", "1", "2", "3", "4", "5", "6", "7", "8", "1", "2", "3", "4", "5", "6", "7", "8", "1", "2", "3", "4", "5", "6", "7", "8", "1", "2", "3", "4", "5", "6", "7", "8"),
distance = c(2, 3, 3, 4, 6, 6, 7, 15, 2, 1, 2, 5, 5, 5, 6, 15, 4, 4, 3, 5, 5, 5, 6, 15, 5, 5, 5, 4, 4, 5, 6, 15, 7, 7, 7, 6, 4, 6, 7, 15, 6, 6, 6, 6, 4, 2, 5, 15, 7, 7, 7, 7, 5, 5, 6, 15, 6, 6, 6, 6, 4, 4, 10, 15, 11, 11, 11, 11, 11, 11, 5, 12, 11, 11, 11, 11, 11, 11, 11, 1, 11, 11, 11, 11, 11, 11, 11, 1)
)
预期结果:
ID.y ID.x distance
1: 55 1 2
2: 56 2 1
3: 57 3 3
4: 58 4 4
5: 59 5 4
6: 60 6 2
7: 63 7 5
8: NA 8 NA
I'm using this code is to complete a fuzzy join using stringdist_join, as described in this question.我有两个需要匹配的数据集(因此ID.x和ID.y)。就我而言,我的测验前和测验分数需要与多个不可靠的特征相匹配。
答案 0 :(得分:1)
我不清楚我为什么ID.x 62和ID.y 7距离5不可行。
假设ID.x 62,ID.y 7和距离5是可以接受的,则可以使用data.table
:
setorder(DT, distance)
choseny <- c()
ans <- DT[,
{
y <- setdiff(ID.y, choseny)[1L]
choseny <- c(choseny, y)
.(ID.y=y, dist=.SD[ID.y==y, distance[1L]])
},
by=.(ID.x)]
setorder(ans, ID.x)[]
输出:
ID.x ID.y dist
1: 55 1 2
2: 56 2 1
3: 57 3 3
4: 58 4 4
5: 59 5 4
6: 60 6 2
7: 61 <NA> <NA>
8: 62 7 5
答案 1 :(得分:0)
我不确定这是否真的是理想的解决方案,但这应该会有所帮助。虽然不是超级优雅,但是看起来很像所需的输出。
DT[, .(ID.y
, distance
, Row.Num = rank(distance)
, Row.Num.ID = rank(ID.y)), by = list(ID.x)][, .SD[Row.Num == min(Row.Num) ], by = ID.x][, .SD[Row.Num.ID == min(Row.Num.ID) ], by = ID.x]
> ID.x ID.y distance Row.Num Row.Num.ID
1: 55 1 2 1.0 1
2: 56 2 1 1.0 2
3: 57 3 3 1.0 3
4: 58 4 4 1.5 4
5: 59 5 4 1.0 5
6: 60 6 2 1.0 6
7: 61 5 5 2.0 5
8: 62 5 4 1.5 5
答案 2 :(得分:0)
我不太了解data.table
,因此我只能给您tidyverse
解决方案。但这也许会对您有所帮助:)
library(tidyverse)
ID_y <- unique(DT$ID.y)
DT %>%
as_tibble() %>%
group_by(ID.x) %>%
mutate(min_dist = min(distance)) %>%
arrange(min_dist) %>%
nest() %>%
mutate(data = data %>% map(~ {
min_row <- .x %>%
filter(ID.y %in% ID_y) %>%
filter(distance == min(distance)) %>%
slice(1)
ID_y <<- ID_y[ID_y != min_row$ID.y]
min_row
})) %>%
unnest() %>%
select(-min_dist) %>%
arrange(ID.x)
我正在保存ID.y
的所有唯一值。然后,我计算所有组合的最小距离,并以此最小距离进行排列,以首先在map
循环中解决那些组合。在过滤了最小距离之后,我从向量中删除了ID.y
,因此其他ID.x
仅在左边的ID.y
中进行搜索。