使用 dplyr::mutate 遍历 stringdist 中的所有可用方法

Using dplyr::mutate to loop through all available methods in stringdist

我正在做一些模糊文本匹配来匹配学校名称。这是我的数据示例,它是一个小标题中的两列:

data <- tibble(school1 = c("abilene christian", "abilene christian", "abilene christian", "abilene christian"),
               school2 = c("a t still university of health sciences", "abilene christian university", "abraham baldwin agricultural college", "academy for five element acupuncture"))
data
# A tibble: 4 x 2
school1           school2                                
  <chr>             <chr>                                  
1 abilene christian a t still university of health sciences
2 abilene christian abilene christian university           
3 abilene christian abraham baldwin agricultural college   
4 abilene christian academy for five element acupuncture 

我想做的是使用 stringdist 到 运行 通过所有可用的 methods 和 return 一个看起来像这样的 table,除了每个方法的一列和值 returned:

之外,我的原始文本仍然存在
# A tibble: 4 x 12
  school1           school2       osa    lv    dl hamming   lcs qgram cosine jaccard    jw soundex
  <chr>             <chr>       <dbl> <dbl> <dbl>   <dbl> <dbl> <dbl>  <dbl>   <dbl> <dbl>   <dbl>
1 abilene christian a t still …  29.0  29.0  29.0     Inf  36.0  24.0 0.189    0.353 0.442    1.00
2 abilene christian abilene ch…  11.0  11.0  11.0     Inf  11.0  11.0 0.0456   0.200 0.131    0   
3 abilene christian abraham ba…  28.0  28.0  28.0     Inf  35.0  25.0 0.274    0.389 0.431    1.00
4 abilene christian academy fo…  28.0  28.0  28.0     Inf  37.0  29.0 0.333    0.550 0.445    1.00

我可以使用以下 for 循环使它工作:

  method_list <- c("osa", "lv", "dl", "hamming", "lcs", "qgram", "cosine", "jaccard", "jw", "soundex")
    for (i in method_list) {
  data[, i] <- stringdist(data$school1, data$school2, method = i)
}

我想做的是将其转换为更具可读性的 dplyr 语法,但我无法让循​​环与 mutate 一起工作。这是我拥有的:

for (i in method_list) {
      ft_result <- data %>% 
                     mutate(i = stringdist(school1, school2, method = i))            
    }

运行 此 return 添加到我的原始数据中的 1 个附加列称为 "i",每行的值为 1。

问题 1:for-loop 是完成我想要达到的目标的最佳方式吗?我查看了 purrr 以查看是否可以使用 map 或 invoke 之类的功能,但我认为这些功能中的任何一个都无法满足我的需求。

问题 2:如果 for-loop 是可行的方法,我怎样才能让它与 mutate 一起工作?我尝试使用 mutate_at,但也没有用。

这似乎是一个很好的地方 purrr::map_dfc

这里的一般想法是通过将每个方法作为输入传递的函数进行映射,并将结果包装在数据帧中。 purrr::set_names也派上用场了。


library(tidyverse)
library(stringdist)

method_list <- c("osa", "lv", "dl", "hamming", "lcs", "qgram",
                 "cosine", "jaccard", "jw", "soundex")

tb <- starwars[c("name", "homeworld")]

method_list %>%
  map_dfc(function(str_method) {
    data_frame(stringdist(tb$name, tb$homeworld, method = str_method))
    }
  ) %>%
  set_names(method_list) %>%
  bind_cols(tb, .)
#> Warning in do_dist(a = b, b = a, method = method, weight = weight, maxDist
#> = maxDist, : Non-printable ascii or non-ascii characters in soundex.
#> Results may be unreliable. See ?printable_ascii.
#> # A tibble: 87 x 12
#>                  name homeworld   osa    lv    dl hamming   lcs qgram
#>                 <chr>     <chr> <dbl> <dbl> <dbl>   <dbl> <dbl> <dbl>
#>  1     Luke Skywalker  Tatooine    13    13    13     Inf    18    18
#>  2              C-3PO  Tatooine     8     8     8     Inf    13    13
#>  3              R2-D2     Naboo     5     5     5       5    10    10
#>  4        Darth Vader  Tatooine     8     8     8     Inf    13    13
#>  5        Leia Organa  Alderaan     8     8     8     Inf    11     9
#>  6          Owen Lars  Tatooine     9     9     9     Inf    15    11
#>  7 Beru Whitesun lars  Tatooine    16    16    16     Inf    22    16
#>  8              R5-D4  Tatooine     8     8     8     Inf    13    13
#>  9  Biggs Darklighter  Tatooine    14    14    14     Inf    19    17
#> 10     Obi-Wan Kenobi   Stewjon    13    13    13     Inf    17    15
#> # ... with 77 more rows, and 4 more variables: cosine <dbl>,
#> #   jaccard <dbl>, jw <dbl>, soundex <dbl>