2016-08-15 3 views
1

R + tm: Как удалить дубликаты элементов в списке на основе семантического сходства? v<-c("bank","banks","banking", "ford_suv',"toyota_suv","nissan_suv"). Моим ожидаемым решением будет c("bank", "ford_suv',"toyota_suv","nissan_suv"). То есть, банки, банки и банки должны быть сокращены до одного термина «банк». SnowBall::stemming не вариант, потому что я должен сохранить вкус газетных стилей разных стран. Любая помощь или направление будут полезны.удалить дубликаты из списка на основе семантической подобия/родства

+1

Если вы не презираете 'для следующей итерации цикла, возможно, [это] (https://www.dropbox.com/s/yepnihx03ar2dkx/relatedness.txt?dl=0) может быть полезно. – Abdou

ответ

5

Мы могли бы вычислить расстояние Левенштейна между словами, используя adist и перегруппировать их в кластеры с помощью hclust

d <- adist(v) 
rownames(d) <- v 

который дает матрицу расстояния между терминами:

#    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] 
#bank    0 1 3 8 9 8 2 13 6  5  3  4 
#banks    1 0 3 7 9 7 2 13 6  6  2  5 
#banking   3 3 0 8 10 8 3 13 7  6  3  7 
#ford_suv   8 7 8 0 5 6 8 12 7  7  8  4 
#toyota_suv  9 9 10 5 0 6 9 7 4  9  9  9 
#nissan_suv  8 7 8 6 6 0 8 13 10  4  8 10 
#banker   2 2 3 8 9 8 0 12 6  6  1  6 
#toyota_corolla 13 13 13 12 7 13 12 0 8 13 12 12 
#toyota   6 6 7 7 4 10 6 8 0  6  7  5 
#nissan   5 6 6 7 9 4 6 13 6  0  7  6 
#bankers   3 2 3 8 9 8 1 12 7  7  0  6 
#ford    4 5 7 4 9 10 6 12 5  6  6  0 

Тогда мы можем передать его hclust с использованием method = ward.D

cl <- hclust(as.dist(d), method = "ward.D") 
plot(cl) 

Что дает:

enter image description here

Мы видим 4 различных кластеров (что можно проиллюстрировать с помощью rect.hclust(cl, 4))

enter image description here

Теперь мы можем превратить этот результат в data.frame и помечать каждый кластер с его кратчайшим сроком:

library(dplyr) 
data.frame(group = cutree(cl, 4)) %>% 
    tibble::rownames_to_column("term") %>% 
    group_by(group) %>% 
    mutate(tag = term[nchar(term) == min(nchar(term))]) 

Что дает:

#Source: local data frame [12 x 3] 
#Groups: group [4] 
# 
#    term group  tag 
#   <chr> <int> <chr> 
#1   bank  1  bank 
#2   banks  1  bank 
#3   banking  1  bank 
#4  ford_suv  2  ford 
#5  toyota_suv  3 toyota 
#6  nissan_suv  4 nissan 
#7   banker  1  bank 
#8 toyota_corolla  3 toyota 
#9   toyota  3 toyota 
#10   nissan  4 nissan 
#11  bankers  1  bank 
#12   ford  2  ford 

Если мы хотим извлечь только уникальный tag для каждого кластера, мы могли бы добавить ... %>% distinct(tag) %>% .$tag к трубе, которые дадут:

#[1] "bank" "ford" "toyota" "nissan" 

Reference

?adist

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

?hclust

Эта функция выполняет иерархического кластерного анализа с использованием набора несходства ибо п объекты, которые сгруппированы.Первоначально каждый объект присваивается его собственному кластеру, а затем алгоритм продолжается , итеративно, на каждом этапе, соединяющем два наиболее похожих кластера, продолжается до тех пор, пока не будет только один кластер.


Примечание: Я использовал данные, предоставленные @Abdou в комментариях, поскольку он представляет собой более полный вариант использования

+2

Это действительно круто! – Abdou

+1

@Steven +100 для вас. Пятьдесят для полного объяснения базовой логики и 50 для перекрестных ссылок. – Pradeep

+0

@Steven: это частые термины из 'findFreqTerms (dtm [mycluster1 [1],], 20)' где 'mycluster'' 'группы <- hclust (dist (m), method =" ward.D ") mycluster <-rect.hclust (groups, 10) #ten clusters', есть способ передать 'hclust' в более высокий' hclust'? Не хочу открывать другой вопрос. Благодарю. – Pradeep

Смежные вопросы