我在两个不同的数据帧 df1 和 df2 -> df1$namedf2$name有两个字符串列。 df1 有超过 10000 行,而 df2 有大约 200+ 行。 例如:

df1 <- data.frame(name = c("Peter P", "Jim Gordon",  "Bruce Wayne", "Tony Stark","Mony Blake" ))

df2<- data.frame(name = c( "Jeter P", "Bruce Wayne", "Mony Blake" ))

注意:dfs 比这些大得多。

我首先使用合并功能。 它首先匹配公共行,但对于“Jeter P”却没有。 然后我使用了来自 Stringdist 库的部分匹配函数amatchmethod = "lv" 它将 Peter P 与 Jeter P 相匹配,这两个不同的人。 我知道 amatch 会改变位置和字母等,但我希望函数搜索 df,同时在匹配字符串时保持字符串的第一个元素相同。

基本上,当我在df2$nameJeter P使用部分字符串匹配时,它只会考虑来自df1$name行,其中字符串以 J 开头作为潜在的部分匹配。 是否可以?

提前致谢。

#1楼 票数:1 已采纳

@RonakShah 今天早些时候发布了一个版本,但后来删除了它,因为他的解决方案不完全符合要求。

这个想法是使用fuzzyjoin包,它有很多功能可以在两个数据集之间进行模糊匹配。 他们中没有一个完全符合这个问题的要求,但这里有一个更长的答案应该这样做。

stringdist_inner_join函数执行常规模糊匹配。 它的工作原理是构建一个复杂的函数以在fuzzy_join使用。 它不导出该函数; 但是您可以创建自己的函数(我称之为stringdist_match ),它只是创建函数并将其导出。 然后结合起来,与一个比较第一个字母,并使用compbined功能( custom_match中) fuzzy_join 这是一些代码。 大多数stringdist_match函数是从fuzzyjoin包中复制的。

library(fuzzyjoin)

stringdist_match <- function(max_dist = 2,
                            method = c("osa", "lv", "dl", "hamming", "lcs", "qgram",
                                       "cosine", "jaccard", "jw", "soundex"),
                            mode = "inner",
                            ignore_case = FALSE,
                            distance_col = NULL, ...) {
  # It's a good idea to force evaluation of all the arguments
  # in case they get changed between when we call this function and 
  # when we use the function it returns.

  force(max_dist)
  force(mode)
  force(ignore_case)
  force(distance_col)
  forceotherargs <- list(...)

  method <- match.arg(method)

  if (method == "soundex") {
    # soundex always returns 0 or 1, so any other max_dist would
    # lead either to always matching or never matching
    max_dist <- .5
  }

  function(v1, v2) {
    if (ignore_case) {
      v1 <- stringr::str_to_lower(v1)
      v2 <- stringr::str_to_lower(v2)
    }

    # shortcut for Levenshtein-like methods: if the difference in
    # string length is greater than the maximum string distance, the
    # edit distance must be at least that large

    # length is much faster to compute than string distance
    if (method %in% c("osa", "lv", "dl")) {
      length_diff <- abs(stringr::str_length(v1) - stringr::str_length(v2))
      include <- length_diff <= max_dist

      dists <- rep(NA, length(v1))

      dists[include] <- stringdist::stringdist(v1[include], v2[include], method = method, ...)
    } else {
      # have to compute them all
      dists <- stringdist::stringdist(v1, v2, method = method, ...)
    }
    ret <- tibble::tibble(include = (dists <= max_dist))
    if (!is.null(distance_col)) {
      ret[[distance_col]] <- dists
    }
    ret
  }
}

# Now the example.  First, create a matching function that
# just does the fuzzy part.
fuzzy_match <- stringdist_match()

# Next create a matching function that just compares first letters.
first_letter_match <- function(col1, col2) 
  sub("(^.).*", "\\1", col1) == sub("(^.).*", "\\1", col2)

# Now create one that requires both to match.
custom_match <- function(col1, col2) 
  first_letter_match(col1, col2) & fuzzy_match(col1, col2)

# Now run the example

df1 <- data.frame(name = c("Peter P", "Jim Gordon",  "Bruce Wayne", "Tony Stark","Mony Blake" ))

df2<- data.frame(name = c( "Jeter P", "Bruce Wayne", "Mony Blake" ))

fuzzy_inner_join(df1, df2, by = "name", match_fun = custom_match)
#>        name.x      name.y
#> 1 Bruce Wayne Bruce Wayne
#> 2  Mony Blake  Mony Blake

reprex 包(v0.3.0) 于 2020 年 2 月 21 日创建

有关stringdist_match所有参数的stringdist_match ,请参阅?fuzzyjoin::stringdist_join

  ask by JohnR translate from so

未解决问题?本站智能推荐:

2回复

计数+识别两个字符串向量中的常用词 [R]

如何编写一个 R 函数,该函数可以采用两个字符串向量并返回常用词的数量以及哪些常用词将 stringvec1 中的元素 1 与 stringvec2 的元素 1、strinvec1 的元素 2 与 stringvec2 的元素 2 等进行比较。 假设我有这些数据: 理想情况下,我有一个函数可以
2回复

字符串匹配两个向量到文本的限制由两者之间的距离限制

我试图找出最有效的方法来匹配两个字符串向量到第三个字符串。 我希望将第二场比赛限制在距离第一场比赛的有限数量的单词或字符之外 假设我有一个像这样的名字数据框: 我有一些这样的文字: 我想在“签名者”数据框中搜索每个名称,并标记它们是否在文本中。 在本杰明富兰克林和乔
1回复

[R]中两列的字符串匹配

我希望匹配多个字符串标准,然后在R中对行进行子集,使用grepl查找匹配。 我从其他帖子中找到了一个很好的解决方案,其中使用了一些特定的代码(但你明白了): subset(GEMA_EO5, grepl(paste(l, collapse="|"),GEMA_EO5$RefSeq_ID))
2回复

R中的快速部分字符串匹配

给定一个字符串texts向量和一个模式patterns向量,我想找到每个文本的任何匹配模式。 对于小数据集,可以使用grepl在R中轻松完成: 此解决方案是正确的,但它不会扩展。 即使使用适度更大的数据集(约500个文本和模式),这段代码也非常慢,在现代机器上每秒仅解决大约100
2回复

R部分字符串匹配忽略全向空格

我在部分字符串匹配方面遇到问题。 我有一对人,我需要比较他们的名字。 为此,我对两个姓氏进行了两个方向的charmatch运算,以查看name1是否为name2的一部分,反之亦然。 我下面有一个小的数据集来演示这个问题。 我在下面使用charmatch; 我也使用了pmatch,它返回
2回复

R中的字符串匹配和操作

我在清理数据方面取得了进展: 真实值是这样的:190312-4184811。 所以有一个模式,前六个整数是一个日期,如 19 = 2019 03 = 三月和 12 = 天。 其他七个数字是随机的。 我清理了很多非信息模式,但在这里我不知道如何处理这么多不同的模式。 我尝试过类似的方法,但我认为
1回复

使用%in%运算符在R中进行部分字符串匹配?

我很想知道是否可以使用R中的%in%运算符进行部分字符串匹配。我知道有很多方法可以使用stringr等来查找部分字符串匹配,但是我当前的代码使用起来更容易%in%运算符。 例如,假设此向量: 我希望每个都是TRUE,因为字符串包含“ Withdrawn”,但是只有第一个是TRUE:
2回复

R:通过正则表达式提取字符串匹配部分的列表

假设我需要从字符串中提取不同的部分作为列表,例如我想将字符串"aaa12xxx"分成三部分。 一种可能性是做三个gsub调用: 当然这看起来很浪费(即使它在for循环中)。 是不是只有从正则表达式和测试字符串返回部件列表的函数?