SparkR: нечеткое совпадение строк Левенштейна между двумя переменными из двух кадров данных Spark - PullRequest
0 голосов
/ 31 августа 2018

У меня есть 2 кадра данных Spark

library(SparkR); library(magrittr)

df1 <- createDataFrame(data.frame(var1 = c("rat", "cat", "bat")))
df2 <- createDataFrame(data.frame(var2 = c("cat3", "bat1", "dog", "toy")))

Мне нужно нечеткое сопоставление разных длинных var1 и var2 из разных Spark DataFrames df1 и df2 с использованием функции Левенштейна в SparkR, чтобы получить желаемый результат.

desired_df <- createDataFrame(data.frame(var2 = c("cat3", "bat1", "dog", "toy"),
                                  var3 = c("cat", "bat", NA_character_, NA_character_)))

Я начал со следующего кода:

df3 <- df2 %>% SparkR::mutate(dist = levenshtein(df2$var2, df1$var1))

но застрял с ошибками:

org.apache.spark.sql.AnalysisException: Resolved attribute(s) var1#176 missing from var2#178 in operator !Project [var2#178, levenshtein(var2#178, var1#176) AS dist#181].;;
!Project [var2#178, levenshtein(var2#178, var1#176) AS dist#181]

Пожалуйста, сообщите.

1 Ответ

0 голосов
/ 01 сентября 2018

Ваша ошибка - ссылаться на столбцы из таблицы, отсутствующей в плане выполнения.

Добавление crossJoin исправит это:

dist_df <- df1 %>%
  crossJoin(df2) %>% 
  withColumn("dist", levenshtein(df1$var1, df2$var2)) 
dist_df %>% head()
  var1 var2 dist              
1  rat cat3    2
2  rat bat1    2
3  rat  dog    3
4  rat  toy    3
5  cat cat3    1
6  cat bat1    2

Отсюда вы можете использовать стандартные методы ( Как выбрать первый ряд каждой группы? ), чтобы найти наиболее близкое совпадение, например:

best_matches <- dist_df %>% 
  groupBy("var2") %>% 
  agg(struct(dist_df$dist, dist_df$var1) %>% min() %>% alias("match"))

threshold <- 1  # Maximum match distance to keep

result <- best_matches %>% 
  select(
    best_matches$var2, 
    when(best_matches$match.dist <= threshold, best_matches$match.var1) %>% 
      alias("var1"))

result %>% head()
  var2 var1
1  dog <NA>
2 bat1  bat
3 cat3  cat
4  toy <NA>

Пожалуйста, имейте в виду, что этот подход очень неэффективен. Spark предоставляет лучшие параметры ( Эффективное сопоставление строк в Apache Spark ), но они еще не представлены в SparkR и лишь частично реализованы в sparklyr.

Если вы хотите сохранить все записи, независимо от качества, просто удалите when:

best_matches %>% select(best_matches$var2, best_matches$match.var1) %>% head()
  var2 var1
1  dog  bat
2 bat1  bat
3 cat3  cat
4  toy  bat
...