【问题标题】:Fuzzy matching (and overwriting) vector entries模糊匹配(和覆盖)向量条目
【发布时间】:2020-10-21 10:06:05
【问题描述】:

我有 5 个列名的向量,它们相似,但不完全相同。

我正在尝试根据vector1 中的名称来更正vector2vector3vector4vector5 中的条目。

我得到了一些想法herehere,导致下面的代码。但最后,我什至在比较前两个向量时遇到了困难。更不用说覆盖它们了。

library(dplyr)
library(fuzzyjoin)


vector1 <- c("something","nothing", "anything", "number4")
vector2 <- c("some thing","no thing","addition", "anything", "number4")
vector3 <- c("some thing wrong","nothing", "anything_")
vector4 <- c("something","nothingg", "anything", "number_4")
vector5 <- c("something","nothing", "anything happening", "number4")

我是这样开始的:

apply(adist(x = vector1, y = vector2), 1, which.min)

data.frame(string_to_match = vector1, 
           closest_match = vector2[apply(adist(x = vector1, y = vector2), 1, which.min)])

           
  string_to_match closest_match
1       something    some thing
2         nothing      no thing
3        anything      anything
4         number4       number4

有没有办法在这个解决方案中添加距离并根据距离覆盖向量?

想要的结果:

  string_to_match closest_match  distance
1       something    some thing   1
2         nothing      no thing   1
3        anything      anything   0
4         number4       number4   0

vector1 <- c("something","nothing", "anything", "number4")
vector2 <- c("something","nothing","addition", "anything", "number4")
vector3 <- c("something","nothing", "anything")
vector4 <- c("something","nothing", "anything", "number4")
vector5 <- c("something","nothing", "anything", "number4")

有没有人能让我走上正轨?

【问题讨论】:

  • 我注意到您想要的结果删除了“addition”,它可能与“anything”最接近。如果这对你来说太远了,你可以调整 max_dist 来消除它

标签: r string dplyr fuzzy-comparison fuzzyjoin


【解决方案1】:

fuzzyjoin 函数将添加距离度量。如果只选择最接近的匹配列/向量,则不需要覆盖。

library(fuzzyjoin); library(dplyr)
vector1 <- c("something","nothing", "anything", "number4")
vector2 <- c("some thing","no thing","addition", "anything", "number4")
vector3 <- c("some thing wrong","nothing", "anything_")
vector4 <- c("something","nothingg", "anything", "number_4")
vector5 <- c("something","nothing", "anything happening", "number4")

# solution for your desired output for vector 2
stringdist_left_join(x = tibble(things = vector1), y = tibble(things = vector2), 
                     max_dist = 1, distance_col = "distance")
#> Joining by: "things"
#> # A tibble: 4 x 3
#>   things.x  things.y   distance
#>   <chr>     <chr>         <dbl>
#> 1 something some thing        1
#> 2 nothing   no thing          1
#> 3 anything  anything          0
#> 4 number4   number4           0

# fuller solution for vector 3 or any other
(full_table_of_possible_matches_for_vector3 <- stringdist_left_join(x = tibble(things = vector3), 
                                                                    y = tibble(things = vector1), 
                                                                    max_dist = 99, distance_col = "distance"))
#> Joining by: "things"
#> # A tibble: 12 x 3
#>    things.x         things.y  distance
#>    <chr>            <chr>        <dbl>
#>  1 some thing wrong something        7
#>  2 some thing wrong nothing         10
#>  3 some thing wrong anything        11
#>  4 some thing wrong number4         14
#>  5 nothing          something        3
#>  6 nothing          nothing          0
#>  7 nothing          anything         2
#>  8 nothing          number4          6
#>  9 anything_        something        5
#> 10 anything_        nothing          3
#> 11 anything_        anything         1
#> 12 anything_        number4          8
(table_of_closest_matches <- full_table_of_possible_matches_for_vector3 %>%
  group_by(things.x) %>%
  mutate(rank = row_number(distance)) %>%
  filter(rank == 1))
#> # A tibble: 3 x 4
#> # Groups:   things.x [3]
#>   things.x         things.y  distance  rank
#>   <chr>            <chr>        <dbl> <int>
#> 1 some thing wrong something        7     1
#> 2 nothing          nothing          0     1
#> 3 anything_        anything         1     1
  #slice_min(distance, with_ties = FALSE) # can't use slice_min or order will mess up
(new_vector3 <- table_of_closest_matches$things.y)
#> [1] "something" "nothing"   "anything"

(new_vector2 <- stringdist_left_join(x = tibble(things = vector2), 
                                     y = tibble(things = vector1), 
                                     max_dist = 99, distance_col = "distance") %>%
    group_by(things.x) %>%
    mutate(rank = row_number(distance)) %>%
    filter(rank == 1) %>%
    .$things.y)
#> Joining by: "things"
#> [1] "something" "nothing"   "anything"  "anything"  "number4"

reprex package (v0.3.0) 于 2021-01-06 创建

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 2021-10-29
    • 2015-02-07
    相关资源
    最近更新 更多