Я ищу способ ускорить следующий подход. Любые указатели очень приветствуются. Где узкие места?В R - самый быстрый путь, попарно сравнивающий символьные строки по подобию
Скажем, у меня есть следующий data.frame
:
df <- data.frame(names=c("A ADAM", "S BEAN", "A APPLE", "J BOND", "J BOND"),
v1=c("Test_a", "Test_b", "Test_a", "Test_b", "Test_b"),
v2=c("Test_c", "Test_c", "Test_d", "Test_d", "Test_d"))
Я хочу, чтобы сравнить каждую пару строк в df
на их JaroWinkler сходства.
С некоторой помощью других (see this post), я был в состоянии построить этот код:
#columns to compare
testCols <- c("names", "v1", "v2")
#compare pairs
RowCompare= function(x){
comp <- NULL
pairs <- t(combn(nrow(x),2))
for(i in 1:nrow(pairs)){
row_a <- pairs[i,1]
row_b <- pairs[i,2]
a_tests <- x[row_a,testCols]
b_tests <- x[row_b,testCols]
comp <- rbind(comp, c(row_a, row_b, TestsCompare(a_tests, b_tests)))
}
colnames(comp) <- c("row_a","row_b","names_j","v1_j","v2_j")
return(comp)
}
#define TestsCompare
TestsCompare=function(x,y){
names_j <- stringdist(x$names, y$names, method = "jw")
v1_j <-stringdist(x$v1, y$v1, method = "jw")
v2_j <-stringdist(x$v2, y$v2, method = "jw")
c(names_j,v1_j, v2_j)
}
Это генерирует правильный вывод:
output = as.data.frame(RowCompare(df))
> output
row_a row_b names_j v1_j v2_j
1 1 2 0.4444444 0.1111111 0.0000000
2 1 3 0.3571429 0.0000000 0.1111111
3 1 4 0.4444444 0.1111111 0.1111111
4 1 5 0.4444444 0.1111111 0.1111111
5 2 3 0.4603175 0.1111111 0.1111111
6 2 4 0.3333333 0.0000000 0.1111111
7 2 5 0.3333333 0.0000000 0.1111111
8 3 4 0.5634921 0.1111111 0.0000000
9 3 5 0.5634921 0.1111111 0.0000000
10 4 5 0.0000000 0.0000000 0.0000000
Однако, мой реальный data.frame имеет 8 миллионов наблюдений, и я делаю 17 сравнений. Для того, чтобы запустить этот код занимает дни ...
Я ищу способы, чтобы ускорить этот процесс:
- Должен ли я использовать матрицы вместо data.frames?
- Как распараллелить этот процесс?
- Векторизация?
Честно говоря, гораздо проще сравнивать каждый столбец независимо: 'lapply (df, stringdist :: stringdistmatrix, method = 'jw')'. [stringdist имеет встроенную встроенную распараллеливание] (https://www.rdocumentation.org/packages/stringdist/versions/0.9.4.4/topics/stringdist-parallelization), хотя вам нужно убедиться, что все сконфигурировано. – alistaire
Чтобы расширить этот подход, чтобы вернуться к тому, что у вас есть, 'library (tidyverse); df%>% map (stringdist :: stringdistmatrix, method = 'jw')%>% map_df (broom :: tidy, .id = 'var')%>% spread (var, distance) '. Я также недавно столкнулся с [multidplyr] (http://www.business-science.io/code-tools/2016/12/18/multidplyr.html), хотя есть много способов распараллеливать. – alistaire
@alistaire Мне это нравится! Спасибо. Есть ли способ различать разные методы? Скажем, точное совпадение строк на v1 и совпадение «soundex» на v2. Возможно ли это с помощью 'stringdist :: stringdistmatrix'? –