SparkR:levenshtein 模糊字符串匹配来自 2 个 Spark 数据帧的 2 个变量
SparkR: levenshtein Fuzzy string matching between 2 variables from 2 Spark dataframes
我有 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")))
我需要使用 SparkR 的 levenshtein 函数对来自不同 Spark DataFrames df1 和 df2 的不同长度的 var1 和 var2 进行模糊匹配,以便获得所需的输出。
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]
请指教。
您的错误是引用了 table 中不存在于执行计划中的列。
添加 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 提供了更好的选项 (Efficient string matching in 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
我有 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")))
我需要使用 SparkR 的 levenshtein 函数对来自不同 Spark DataFrames df1 和 df2 的不同长度的 var1 和 var2 进行模糊匹配,以便获得所需的输出。
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]
请指教。
您的错误是引用了 table 中不存在于执行计划中的列。
添加 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 提供了更好的选项 (Efficient string matching in 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