R:根据两个关键变量匹配:精确数值变量和最接近的字符串变量



我有两个数据集,其中包含一些相同个体的标识符。

df1更完整,有三个变量:(1) 个人姓名,(2) 区域注册 ID,(3) 注册 ID 的区域代码。

df2仅通知 (1) 和 (2)(即名称和区域注册 ID,而不是区域代码)。

个人由区域代码区域注册 ID 唯一标识。 不同的区域可能会通知相同的 ID 号。此外,同一个人在两个数据集中始终具有相同的区域注册 ID,但在这些数据集中可能没有完全相同的姓名拼写。

我想通过将每一行与df1一起使用作为关键变量来添加区域代码df2,使用确切的区域注册 ID 以及数据集之间最接近的名称(拼写相似的名称)。请考虑以下示例:

library("tidyverse")

df1 <- data.frame(name = c("flaviasillva", "flaviasilvaa", "rodrigomaia", "mariaconceicao",
"felipesantos", "mateussauro",
"flaviasilva",
"abrahaoemidiopedreiradealbuquerque"),
regional_registration_id = c(rep(1,4),
rep(2,2),
3,
4),
region_code = c("A", "B", "C", "D",
"B", "D",
"F",
"Z"))

df2 <- data.frame(name = c("flaviasilva", "rodrigommaia", "filipesantos", "abrahaoemidiopdealbuquerque"),
regional_registration_id = c(1, 1, 2, 4))

我想要的输出应该是:

name regional_registration_id region_code
1                 flaviasilva                        1           A
2                 flaviasilva                        1           B
3                filipesantos                        2           B
4 abrahaoemidiopdealbuquerque                        4           Z

我们可以在dplyr中使用agreprowwise。您需要使用max.distance设置。

如果您只有一个匹配项,则此方法有效,否则将引发错误。

library(tidyverse)
df2 %>% 
rowwise() %>% 
mutate(name = agrep(name,
df1[df1$regional_registration_id == regional_registration_id, ]$name,
value = TRUE)) %>% 
ungroup() %>% 
left_join(df1, by = c("name", "regional_registration_id"))
#> # A tibble: 2 × 3
#>   name         regional_registration_id region_code
#>   <chr>                           <dbl> <chr>      
#> 1 flaviasillva                        1 A          
#> 2 felipesantos                        2 B

如果您想先查看所有可能的匹配项,我们可以使用以下方法。下一步是考虑加入哪个match_id(始终是第一个或所有 id,还是仅与另一个条件匹配的 id?

library("tidyverse")
df2 %>% 
rowwise(name) %>%  
summarise(
tibble(match_name = agrep(name,
df1[df1$regional_registration_id == regional_registration_id, ]$name,
value = TRUE),
match_id = seq_len(length(match_name))),
regional_registration_id = regional_registration_id
)
#> `summarise()` has grouped output by 'name'. You can override using the `.groups`
#> argument.
#> # A tibble: 3 × 4
#> # Groups:   name [2]
#>   name         match_name   match_id regional_registration_id
#>   <chr>        <chr>           <int>                    <dbl>
#> 1 flaviasilva  flaviasillva        1                        1
#> 2 flaviasilva  flaviasilvaa        2                        1
#> 3 filipesantos felipesantos        1                        2

创建于 2022-10-03 由 reprex 软件包 (v0.3.0)

这是一个带有stringdist_join的解决方案,这是fuzzyjoin包中非常有用的函数,用于基于模糊或近似匹配合并数据帧。

此功能的关键要素是 (i) 距离的选择,或(非)相似性,度量和 (ii) 选择最大距离阈值。这里选择的度量是 Jaro-Winkler 距离,阈值设置为 0.2(鉴于完全相似性为 0,完全不相似性为 1,因此相对严格):

library(fuzzyjoin)
library(dplyr)
df1 %>%
stringdist_join(
., df2,
by  = c("name", "regional_registration_id"),
# use left join:
mode = 'left',
# use Jaro-Winkler distance metric:
method = "jw",
# maximum distance:
max_dist = 0.2,
# name for distance column:
distance_col = 'dist') %>%
# remove rows for which no matches were found:
filter(!is.na(name.y)) %>%
# select relevant columns:
select(c(4,3,5)) %>%
# renamce columns with function:
rename_with(~sub("\.x|y", "", .), matches("\.x|y"))
name. region_code regional_registration_id.
1  flaviasilva           A                         1
2  flaviasilva           B                         1
3 filipesantos           B                         2

最新更新