2016-01-25 86 views
4

我的目標是在的大計劃中,只打印具有相似/相同字段名稱而沒有重複的行。即,如果三行重複,則只打印一次(而不是每個兩兩比較)。使用條件減少'while循環'

的最小數據集和庫重現:

library(stringdist) 
trye <- data.frame(names = c('aa','aa','aa','bb','bb','cc'), 
        values = 1:6, 
        id = c('row 1', 'row 2', 'row 3', 'row 4', 'row 5', 'row 6'), 
        stringsAsFactors = FALSE) 

我的預期產出將具有相同/相似名稱的行(1,2,3,4,5):

trye 
# names values id 
# 1 aa  1 row 1 
# 2 aa  2 row 2 
# 3 aa  3 row 3 
# 4 bb  4 row 4 
# 5 bb  5 row 5 

這裏有兩個嘗試,但沒有工作(其他一些修改紛紛拋出錯誤):

#this one prints row 1,2,3,3,5,5 
i <- 1 
while (i < length(trye$names)) { 

    dupe <- amatch(trye$names[[i]],trye$names[-i], maxDist = 1) 

    if(dupe + 1 > 0) { 
    print(trye[i,]) 
    duperow <- dupe + 1 
    print(trye[duperow,]) 
    trye <- trye[-c(i), ] 
    i <- i + 1 


    } else { 
    i <- i + 1 
    trye <- trye[-c(i), ] 
    } 

} 



# this one prints rows 1,2,4,5 which is almost correct, 
# it's missing row 3 (as it shares the name with row 1 and 2. 
i <- 1 
while (i < length(trye$names)) { 

    dupe <- amatch(trye$names[[i]],trye$names[-i], maxDist = 1) 

    if(dupe + 1 > 0) { 
    print(trye[i,]) 
    duperow <- dupe + 1 
    print(trye[duperow,]) 
    trye <- trye[-c(i,duperow), ] 
    i <- i + 1 


    } else { 
    i <- i + 1 
    trye <- trye[-c(i,duperow), ] 
    } 

} 

請注意THA t實際數據集很大,所以刪除行以使比較更小似乎(或似乎)對我來說是一個好主意,並且實際集合中的最大距離大於1.

+0

所以,你想省略一次出現的行嗎? –

+0

是的,基本上! – erasmortg

+0

這樣的事情? (1:nrow(trye),function(x)sum(adist(trye [x,1],trye [,1])== 0)> 1)使用'adist'而不是amatch – jeremycg

回答

3

您可以使用adist基地,獲得Levenshtein距離,和過濾由那些具有至少一個匹配(除了自己):

sapply(1:nrow(trye), function(x) sum(adist(trye[x,1], trye[,1])==0)>1) 

如果你的數據量非常大,adist是昂貴的,你可以刪除所有重複,除了第一和最後一個:

trye[(!duplicated(trye$names) | rev(!duplicated(rev(trye$names)))),] 

,然後將它們添加回來。您可能還需要檢查openrefine,這可能會加快速度。