2016-01-25 5 views
4

Моя цель, в великой схеме вещей, состоит в том, чтобы печатать только строки, имеющие одинаковое имя одного поля без повторения. То есть, если три строки дублируются, распечатайте каждый из них только один раз (а не каждое попарное сравнение).Редукция 'while loop' с условиями

Минимальный набор данных и библиотеки для воспроизведения:

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), ] 
    } 

} 

Пожалуйста, обратите внимание, ТНО фактический набор данных огромен, поэтому удаление строк, чтобы сделать сравнения меньшими, кажется (или показалось) как хорошая идея для меня, также максимальное расстояние в фактическом наборе больше 1.

+0

так что вы хотите опустить строки с одним вхождением? –

+0

да, в основном! – erasmortg

+0

что-то вроде этого? 'sapply (1: nrow (trye), function (x) sum (adist (trye [x, 1], trye [, 1]) == 0)> 1)'? используя 'adist' вместо amatch – jeremycg

ответ

3

вы можете использовать adist от основание, чтобы получить Левенштейн расстояние и фильтр тех, которые имеют по крайней мере один матч (кроме себя):

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, что может ускорить это.