r - R中的部分字符串匹配并修剪字符

标签 r string-matching fuzzy-search agrep fuzzyjoin

这是一个数据框和一个向量。

df1  <-  tibble(var1 = c("abcd", "efgh", "ijkl", "mnopqr", "qrst"))
vec <-  c("ab", "mnop", "ijk")

现在,对于 var1 中与 vec 中的值最接近的所有值(我想匹配前 n 个字符),仅保留 var1 中 vec 的前 3 个字符,这样所需的解决方案是:

df2 <- tibble(var1 = c("ab", "efgh", "ijk", "mno", "qrst"))

由于“abcd”与 vec 中的“ab”最匹配,因此我们在 df2 中仅保留最多 3 个“ab”字符,即本例中的 2 个,但 vec 中不存在“efgh”,因此我们保留它原样,即 df2 中的“efgh”等等。

我可以使用 dplyr、stringr、fuzzyjoin、agrep 或 fuzzywuzzyr 来完成此操作吗?您可能希望以此处建议的以下内容为基础 https://stackoverflow.com/a/51053674/6762788 ,感谢 Psidom。

df1 %>% 
    mutate(var1 = ifelse(var1 %in% vec, substr(var1, 1, 3), var1))

最佳答案

这是一个两步解决方案。首先,执行模糊匹配并替换前 n 个字符的函数。它运行 agrepl 将输入模式与提供的向量进行匹配,并保留前 n 个字符(如果匹配)。如果没有匹配,则返回NA。其设计目的是通过 lapply 应用于模式向量,因此第二个函数用于将其转换为一个向量。 reducer 接受两个相同长度的向量,并用第二个向量的非缺失值替换第一个向量的所有实例(其中第二个向量不是 NA)。

这一切都包含在几次调用中,并根据需要返回向量。

fuzzy_match_and_replace = function(pattern, vector, n = 3){
  n = min(c(n,nchar(pattern)))
  match = agrepl(pattern,vector)
  pattern_first_n = substr(pattern,1,n)
  vector_first_n = substr(vector,1,n)
  output = rep(NA,length(vector))
  output[match & pattern_first_n == vector_first_n] = pattern_first_n
  return(output)
}

reducer = function(a,b){
  a[!is.na(b)] = b[!is.na(b)]
  return(a)
}


df1  <-  data.frame(var1 = c("abcd", "efgh", "ijkl", "mnopqr", "qrst"), stringsAsFactors = FALSE)
vec <-  c("ab", "mnop", "ijk")
Reduce(reducer,lapply(vec,fuzzy_match_and_replace,vector=df1$var1),init=df1$var1)
#> [1] "ab"   "efgh" "ijk"  "mno"  "qrst"

如果您希望它在变异步骤中工作,您可以使用如下所示的包装器

wrapper = function(pattern, vector, n = 3){
  Reduce(reducer,lapply(pattern,fuzzy_match_and_replace,vector=vector,n=n),init=vector)
}

更新

这是一个更简单的函数(1 步),它利用了 Onyambu 答案中的 adist,但不依赖 max.col,而是使用 vapply code> 它会遍历矩阵来识别匹配并进行替换。

fuzzy_match_and_replace = function(pattern, vector, n = 3, ...){
  matches = adist(pattern,vector,partial=T,...) == 0
  replace = vapply(apply(matches,2,which)
                  ,function(x){
                    if(length(x) > 0) return(substr(pattern,1,n)[x]) else return(NA_character_)
                   }
                  ,FUN.VALUE = c(""))
  vector[!is.na(replace)] = replace[!is.na(replace)]
  return(vector)
}

library(dplyr)
df1  <-  tibble(var1 = c("abcd", "efgh", "ijkl", "mnopqr", "qrst","mnopr"))
vec <-  c("ab", "mnop", "ijk")

df1%>%
  mutate(var1=fuzzy_match_and_replace(vec,var1))
#> # A tibble: 6 x 1
#>   var1 
#>   <chr>
#> 1 ab   
#> 2 efgh 
#> 3 ijk  
#> 4 mno  
#> 5 qrst 
#> 6 mno

关于r - R中的部分字符串匹配并修剪字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51088502/

相关文章:

regex - 在第一个和最后一个逗号上拆分字符串

r - 最佳实践 : Should I try to change to UTF-8 as locale or is it safe to leave it as is?

elasticsearch - 有什么效率更高?模糊搜索还是范围搜索?

java - 如何从java中的字符串创建键/值映射(更复杂)

r - 使用 R 中的模糊/近似字符串匹配合并两个数据框

javascript - 如何设置 fuse.js 选项

css - 在 R Shiny 应用程序中调整flexdashboard仪表的布局?

r - 如何在 Shiny 或 Shiny 的仪表板应用程序中管理我的 R 代码?

python - 使用Python的jellyfish模块获得最佳匹配(部分字符串匹配)

Python处理字符串匹配