如何根据字符串的相似性进行分组

时间:2017-12-02 15:50:21

标签: r

我有这样的数据

df <-structure(list(label = structure(c(5L, 6L, 7L, 8L, 3L, 1L, 2L, 
    9L, 10L, 4L), .Label = c(" holand", " holandindia", " Holandnorway", 
    " USAargentinabrazil", "Afghanestan ", "Afghanestankabol", "Afghanestankabolindia", 
    "indiaAfghanestan ", "USA", "USAargentina "), class = "factor"), 
        value = structure(c(5L, 4L, 1L, 9L, 7L, 10L, 6L, 3L, 2L, 
        8L), .Label = c("1941029507", "2367321518", "2849255881", 
        "2913128511", "2927576083", "4550996370", "457707181.9", 
        "637943892.6", "796495286.2", "89291651.19"), class = "factor")), .Names = c("label", 
    "value"), class = "data.frame", row.names = c(NA, -10L))

我想得到最大的名字(字母),然后看看有多少小名和相似的名字,并将它们分配给一个小组

然后转到另一个下一个大名称并将它们分配给另一个组

直到没有人离开

首先我计算每个的长度,所以我将得到它们的长度

library(dplyr)
dft <- data.frame(names=df$label,chr=apply(df,2,nchar)[,1])
colnames(dft)[1] <- "label"
df2 <- inner_join(df, dft)

现在我可以简单地找到哪个字符串是最长的

df2[which.max(df2$chr),]

现在我应该看到哪些其他字符串的字母与此长字符串相似。我们有这些可能性

Afghanestankabolindia

可以是

A
Af
Afg
Afgh
Afgha
Afghan
Afghane
.
.
.

所有可能的组合,但字母顺序应相同(从左到右),例如它应为Afgh且不能为fAhg

所以我们只有两个与此类似的其他字符串

Afghanestan
Afghanestankabol

这是因为它们应该完全相似,甚至不能分配给同一组的字母不同(超过最大字符串)

欲望输出如下:

label                     value     group
Afghanestan              2927576083     1
Afghanestankabol         2913128511     1
Afghanestankabolindia    1941029507     1
indiaAfghanestan        796495286.2     2
 Holandnorway           457707181.9     3
 holand                 89291651.19     3
 holandindia            4550996370      3
USA                     2849255881      4
USAargentina            2367321518      4
USAargentinabrazil      637943892.6     4

为什么indiaAfghanestan是一个独立的团体?因为它并不完全属于另一个名称(它的名称来自一个或另一个)。它应该是更大名称的一部分

我试图使用这个Find similar strings and reconcile them within one dataframe,但这根本没有帮助我

我找到了其他可能有帮助的东西

require("Biostrings")
pairwiseAlignment(df2$label[3], df2$label[1], gapOpening=0, gapExtension=4,type="overlap")

但我仍然不知道如何将它们分配到一个组

1 个答案:

答案 0 :(得分:2)

你可以尝试

library(magrittr)
df$label %>% 
  tolower %>% 
  trimws %>% 
  stringdist::stringdistmatrix(method = "jw", p = 0.1) %>% 
  as.dist %>% 
  `attr<-`("Labels", df$label) %>% 
  hclust %T>% 
  plot %T>% 
  rect.hclust(h = 0.3) %>% 
  cutree(h = 0.3) %>% 
  print -> df$group

enter image description here

df
# label       value group
# 1           Afghanestan   2927576083     1
# 2       Afghanestankabol  2913128511     1
# 3  Afghanestankabolindia  1941029507     1
# 4      indiaAfghanestan  796495286.2     2
# 5           Holandnorway 457707181.9     3
# 6                 holand 89291651.19     3
# 7            holandindia  4550996370     3
# 8                    USA  2849255881     4
# 9          USAargentina   2367321518     4
# 10    USAargentinabrazil 637943892.6     4

有关stringdist提供的字符串相异度度量的概述,请参阅?stringdist::'stringdist-metrics'