我正在处理下面的一些观察。我的目标是基于欧式距离概念,并考虑向量{x1,x2,x3,x4}
和阈值 0.2 ,以识别彼此匹配/相似的行。行之间的任何小于0.2的距离都被视为相似。
Observation Blood x1 x2 x3 x4
1 A 0.01 0.16 0.31 0.46
2 A 0.02 0.17 0.32 0.47
3 A 0.03 0.18 0.33 0.48
4 B 0.05 0.20 0.35 0.49
5 B 0.06 0.21 0.36 0.50
6 B 0.07 0.22 0.37 0.51
7 AB 0.09 0.24 0.39 0.52
8 AB 0.1 0.25 0.4 0.53
9 AB 0.11 0.26 0.41 0.54
10 O 0.13 0.28 0.43 0.55
11 O 0.14 0.29 0.44 0.56
12 O 0.15 0.3 0.45 0.57
我可以使用一个笨重的双forloop来做到这一点。我想知道是否有一种有效的方法来完成此任务。
预期产量
Observation Blood x1 x2 x3 x4 Match
1 A 0.01 0.16 0.31 0.46 Yes
2 A 0.02 0.17 0.32 0.47 Yes
3 A 0.03 0.18 0.33 0.48 No
4 B 0.05 0.20 0.35 0.49 Yes
5 B 0.06 0.21 0.36 0.50 Yes
6 B 0.07 0.22 0.37 0.51 No
7 AB 0.09 0.24 0.39 0.52 No
8 AB 0.1 0.25 0.4 0.53 Yes
9 AB 0.11 0.26 0.41 0.54 No
10 O 0.13 0.28 0.43 0.55 No
11 O 0.14 0.29 0.44 0.56 Yes
12 O 0.15 0.3 0.45 0.57 Yes
Match Dataset
RowToBeMatched FoundMatches_Bgroup_B FoundMatches_Bgroup_AB FoundMatches_Bgroup_O
1 4 8 11
2 5 NA 12
等等...
答案 0 :(得分:1)
这是使用fuzzyjoin::distance_inner_join
的方法。联接应该非常快,但是我们需要过滤掉具有不同Blood值的自我匹配和巧合匹配。
df %>%
fuzzyjoin::distance_inner_join(df, by = c("x1", "x2", "x3", "x4"),
max_dist = 0.02) %>%
filter(Observation.x != Observation.y,
Blood.x == Blood.y)
输出显示所有具有足够相似匹配的观测值:
Observation.x Blood.x x1.x x2.x x3.x x4.x Observation.y Blood.y x1.y x2.y x3.y x4.y
1 1 A 0.01 0.16 0.31 0.46 2 A 0.02 0.17 0.32 0.47
2 2 A 0.02 0.17 0.32 0.47 1 A 0.01 0.16 0.31 0.46
3 2 A 0.02 0.17 0.32 0.47 3 A 0.03 0.18 0.33 0.48
4 3 A 0.03 0.18 0.33 0.48 2 A 0.02 0.17 0.32 0.47
5 4 B 0.05 0.20 0.35 0.49 5 B 0.06 0.21 0.36 0.50
6 5 B 0.06 0.21 0.36 0.50 4 B 0.05 0.20 0.35 0.49
7 8 AB 0.10 0.25 0.40 0.53 9 AB 0.11 0.26 0.41 0.54
8 9 AB 0.11 0.26 0.41 0.54 8 AB 0.10 0.25 0.40 0.53
9 10 O 0.13 0.28 0.43 0.55 11 O 0.14 0.29 0.44 0.56
10 11 O 0.14 0.29 0.44 0.56 10 O 0.13 0.28 0.43 0.55
11 11 O 0.14 0.29 0.44 0.56 12 O 0.15 0.30 0.45 0.57
12 12 O 0.15 0.30 0.45 0.57 11 O 0.14 0.29 0.44 0.56
此输出可以带回以获取所请求格式的输出:
df %>%
fuzzyjoin::distance_inner_join(df, by = c("x1", "x2", "x3", "x4"),
max_dist = 0.02) %>%
filter(Observation.x != Observation.y,
Blood.x == Blood.y) %>%
select(Observation.x, Blood.x) %>%
rename(Observation = Observation.x,
Blood = Blood.x) %>%
mutate(Match = "Yes") %>%
right_join(df) %>%
replace_na(list(Match = "No"))
Joining, by = c("Observation", "Blood")
Observation Blood Match x1 x2 x3 x4
1 1 A Yes 0.01 0.16 0.31 0.46
2 2 A Yes 0.02 0.17 0.32 0.47
3 2 A Yes 0.02 0.17 0.32 0.47
4 3 A Yes 0.03 0.18 0.33 0.48
5 4 B Yes 0.05 0.20 0.35 0.49
6 5 B Yes 0.06 0.21 0.36 0.50
7 6 B No 0.07 0.22 0.37 0.51
8 7 AB No 0.09 0.24 0.39 0.52
9 8 AB Yes 0.10 0.25 0.40 0.53
10 9 AB Yes 0.11 0.26 0.41 0.54
11 10 O Yes 0.13 0.28 0.43 0.55
12 11 O Yes 0.14 0.29 0.44 0.56
13 11 O Yes 0.14 0.29 0.44 0.56
14 12 O Yes 0.15 0.30 0.45 0.57