r匹配相似的行

时间:2019-04-24 02:15:10

标签: r match euclidean-distance

我正在处理下面的一些观察。我的目标是基于欧式距离概念,并考虑向量{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

等等...

1 个答案:

答案 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