2015-08-29 32 views
1

我想看看我的數據集中的單詞是否出現在某個文本中。當使用grepl時,您只能得到完全匹配。與agrepl可能做部分匹配。但是,我沒有得到預期的結果。只允許一個字母差異時如何獲得匹配?

示例數據:

dt <- structure(list(id = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L), 
        words = c("weg", "verte", "spiegelend", "spiegeld", "einde", "spiegel", "spiegelende", "weg", "spiegelend", "asfalt", "fata", "morgana")), 
       .Names = c("id", "words"), row.names = c(NA, -12L), class = c("data.table", "data.frame")) 

有了:

dt <- dt[, .(id, words, 
      match1=mapply(grepl, words, 
          "hoe komt het dat de weg in de verte soms spiegelend lijkt"), 
      match2=mapply(agrepl, words, 
          "hoe komt het dat de weg in de verte soms spiegelend lijkt", 
          MoreArgs=list(max.distance=1L)))] 

我得到:

> dt 
    id  words match1 match2 
1: 0   weg TRUE TRUE 
2: 0  verte TRUE TRUE 
3: 0 spiegelend TRUE TRUE 
4: 0 spiegeld FALSE TRUE 
5: 0  einde FALSE FALSE 
6: 0  spiegel TRUE TRUE 
7: 0 spiegelende FALSE TRUE 
8: 1   weg TRUE TRUE 
9: 1 spiegelend TRUE TRUE 
10: 1  asfalt FALSE FALSE 
11: 1  fata FALSE FALSE 
12: 1  morgana FALSE FALSE 

正如你可以看到,從greplagrepl結果的行4和7的不同。但是,我只想在最大一個字母差異時進行比賽。因此match2第4行的匹配應該是FALSE。更改參數如max.distancecosts也不會導致所需的結果。而且,第6行的兩個匹配也應該是FALSE

例如:從文本詞「spiegelend」,字「spiegelende」應該給比賽(只有一個字母之差),但這個詞「spiegeld」(兩個字母的區別)和「spiegel」(三個字母的差異)應該而不是給一個匹配。

條件允許(但不是在同一時間):

  • 一個字母以上(例如: 「spiegelende」 應該給匹配),或
  • 一個字母以下(例如: 「spiegelen」 應該給出一個匹配),或者
  • 一個拼寫錯誤(例如: 「spiehelend」 應該給出一個匹配)

有關如何解決此問題的任何想法?

+0

@ Jonny5其實,'agrepl'使用Levenshtein距離。但是,使用'?agrepl'中指定的參數我無法獲得所需的結果。 – Jaap

+0

@nongkrong當我想將某個矢量中的單詞與特定文本(如示例中指定的)匹配時,我該怎麼做? – Jaap

+0

@nongkrong @nongkrong只考慮了額外的字母,當'words'中的單詞短一個字母時,我沒有得到匹配(另請參見問題中的指定條件) – Jaap

回答

2

兩種方法來解決這個問題,通過nongkrong和RHertel匹配的方法:

dt <- cbind(dt[,c("id", "words")], 
     match1=mapply(grepl, dt$words, 
         "hoe komt het dat de weg in de verte soms spiegelend lijkt"), 
     match2=mapply(agrepl, dt$words, 
         "hoe komt het dat de weg in de verte soms spiegelend lijkt", 
         MoreArgs=list(max.distance=1L)), 
     match3=mapply(agrepl, paste0("\\b",dt$words,"\\b"), 
         "hoe komt het dat de weg in de verte soms spiegelend lijkt", 
         MoreArgs=list(max.distance=1L, fixed=F)), 
     match4=apply(adist(dt$words, unlist(strsplit("hoe komt het dat de weg in de verte soms spiegelend lijkt", split=" "))), 
       1, function (x) any(x<=1)) 
        ) 

MATCH3使用單詞邊界\\ B,而match4用途編輯距離(adist)< = 1向量中的單個單詞

2

我想過在這種情況下使用adist()的條件< 2。但我不確定它是否會產生預期的產出。這有幫助嗎?

idx <- which(adist(dt$words,dt2$words) < 2, arr.ind = T) 
dt$match <- (dt$words %in% dt2$words[idx[,2]]) 
#> dt 
# id  words match 
#1 0   weg TRUE 
#2 0  verte TRUE 
#3 0 spiegelend TRUE 
#4 0 spiegeld FALSE 
#5 0  einde FALSE 
#6 0  spiegel FALSE 
#7 0 spiegelende FALSE 
#8 1   weg TRUE 
#9 1 spiegelend TRUE 
#10 1  asfalt FALSE 
#11 1  fata FALSE 
#12 1  morgana FALSE 

數據

dt <- structure(list(id = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L), 
       words = c("weg", "verte", "spiegelend", "spiegeld", "einde", "spiegel", "spiegelende", "weg", "spiegelend", "asfalt", "fata", "morgana")), 
      .Names = c("id", "words"), row.names = c(NA, -12L), class = c("data.table", "data.frame")) 
dt2 <- structure(list(id = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L), 
        words = c("hoe", "komt", "het", "dat", "de", "weg", "in", "de", "verte", "soms", "spiegelend", "lijkt")), 
       .Names = c("id", "words"), row.names = c(NA, -12L), class = c("data.table", "data.frame"))