【问题标题】:Detecting duplicate entries检测重复条目
【发布时间】:2020-09-15 07:32:44
【问题描述】:

我正在尝试编写一个函数来检测表中的两个名称是否相似。假设一个条目是重复的,但写法不同:以下示例说明了这种情况

Ned Flanders and Nedd Flanders
Ned F and Ned F.
Ned Flanders and Nedd Flanders
Ned Flanders and Ned Flamders

我想创建一个函数,该函数能够检测两个名称的大部分字符是否相同,这发生在上面说明的情况中。问题是一个很长的名字可以包含一个小名字的所有字符,即使名字非常不同。

有什么办法解决这个问题吗?您不需要以 100% 的准确率进行检测,这只是确保没有重复的一种额外方法。

我知道该表应该有一个唯一键,但目前这是不可能的,并且考虑过滤器中的其他列不起作用,因为在某些情况下其他列也会发生变化。

duplicity_detect <- function(vec) {
  duplicity<-data.frame(matrix(nrow = 0, ncol = 2))
  colnames(duplicity)<-c('name','nome similar')
  for (i in 1:(length(vec)-1)){
    for (j in (i+1):length(vec)){
      x<-strsplit(gsub(x = vec[i],pattern = " ",replacement = ""),split = "")[[1]]
      y<-strsplit(gsub(x = vec[j],pattern = " ",replacement = ""),split = "")[[1]]

      intersec <- x[x %in% intersect(x, y)]
      if (length(intersec)>0.99*length(x) | length(intersec)>0.99*length(y)){
        duplicity[nrow(duplicity) + 1,] = c(vec[i],vec[j])
      }
    }
  }
  return(duplicity)
}

编辑:

我按照@Shan R的思路重写了函数

duplicity_detect <- function(vec) {
  duplicity  <- lapply(vec, FUN = agrep, vec, value = T)
  duplicity  <- duplicity[lapply(duplicity, length) > 1]
  return(duplicity)
}

【问题讨论】:

  • 试试agrep,近似匹配。 agrep(pattern, x, ignore.case = FALSE, value = FALSE, max.distance = 0.1)
  • 你在读什么类型的表?该函数是否需要从表中读取或仅检查相似性?
  • 你可以考虑一个data.frame,想法是过滤一个包含名字的列
  • 事实上我想获得一个名称相似的新data.frame,这样我就可以确定它是否是重复条目

标签: r string filter


【解决方案1】:

您在文本挖掘中寻找的概念是余弦相似度。它适用于非常长的文档(书本长度)和短文档(单个单词)。

我不能亲自担保,但请看textmineR 包。小插曲在这里: https://cran.r-project.org/web/packages/textmineR/vignettes/b_document_clustering.html

【讨论】:

    【解决方案2】:

    这似乎没问题。它识别出 John Doe 不匹配,并且知道 John Doe 和 Jcob 不同:

    x <- c("Ned Flanders","Ned F", "Ned F.", "Ned Flamders", "John Doe", "Jacob Boyun")
    
    y <- lapply(x, FUN = agrep, x, value = T)
    unique(y[(lapply(y,length) > 1)])
    

    结果:

    [[1]]
    [1] "Ned Flanders" "Ned Flamders"
    
    [[2]]
    [1] "Ned Flanders" "Ned F"        "Ned F."       "Ned Flamders"
    

    【讨论】:

    • 在这里进行了测试,显然效果很好。有没有办法过滤此列表并仅收集检测到另一个类似名称的名称?
    • 长度 > 1 的任何条目都有类似的条目。将尝试更新代码。
    • 我通过添加一个新功能编辑了我的问题,我仍然需要检查更多细节,但它似乎工作得很好
    • 我更新了过滤列表的解决方案。由于这对您有用,请考虑通过单击答案旁边的灰色复选标记来“接受”该解决方案。
    【解决方案3】:

    您可以考虑使用 Python 的 difflib 包并导入 SequenceMatcher。 只要它是可散列的,此类就可以比较任何类型的序列。 .ratio() 以 0.0 到 1.0 之间的浮点数形式返回序列相似度的度量

    1.0 将被证明是相同的。

    from difflib import SequenceMatcher
    
    def check_similarity(col_a, col_b):
        return SequenceMatcher(None, col_a, col_b).ratio()
    
    
    print(check_similarity('Ned Flanders', 'Nedd Flanders'))
    
    print(check_similarity('Neds Flanders', 'Nedd Flanders'))
    
    print(check_similarity('Ned Flanders', 'Ned Flanders'))
    

    【讨论】:

      猜你喜欢
      • 2014-07-10
      • 1970-01-01
      • 1970-01-01
      • 2012-05-09
      • 1970-01-01
      • 2012-12-06
      • 1970-01-01
      • 2014-08-25
      • 1970-01-01
      相关资源
      最近更新 更多