新的Dataframe列作为其他行的通用功能(火花)

发布于 2021-01-29 17:11:24

如何有效地创建一个新列 DataFrame ,它是其他行的功能 spark

这是spark我在这里描述的问题的一种实现:

from nltk.metrics.distance import edit_distance as edit_dist
from pyspark.sql.functions import col, udf
from pyspark.sql.types import IntegerType

d = {
    'id': [1, 2, 3, 4, 5, 6],
    'word': ['cat', 'hat', 'hag', 'hog', 'dog', 'elephant']
}

spark_df = sqlCtx.createDataFrame(pd.DataFrame(d))
words_list = list(spark_df.select('word').collect())

get_n_similar = udf(
    lambda word: len(
        [
            w for w in words_list if (w['word'] != word) and 
            (edit_dist(w['word'], word) < 2)
        ]
    ),
    IntegerType()
)

spark_df.withColumn('n_similar', get_n_similar(col('word'))).show()

输出:

+---+--------+---------+
|id |word    |n_similar|
+---+--------+---------+
|1  |cat     |1        |
|2  |hat     |2        |
|3  |hag     |2        |
|4  |hog     |2        |
|5  |dog     |1        |
|6  |elephant|0        |
+---+--------+---------+

这里的问题是我不知道一种方法,不能先将spark当前行与的其他行进行比较,Dataframe而不必先将值收集到中list。有没有一种方法可以应用其他行的泛型函数而无需调用collect

关注者
0
被浏览
45
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    这里的问题是,我不知道一种方法,可以在不首先将值收集到列表中的情况下,告诉spark将当前行与Dataframe中的其他行进行比较。

    UDF是不是一种选择,在这里(你不能引用分布DataFrameudf)你的逻辑的直接翻译是笛卡尔乘积和汇总:

    from pyspark.sql.functions import levenshtein, col
    
    result = (spark_df.alias("l")
        .crossJoin(spark_df.alias("r"))
        .where(levenshtein("l.word", "r.word") < 2)
        .where(col("l.word") != col("r.word"))
        .groupBy("l.id", "l.word")
        .count())
    

    但实际上,您应该尝试做一些更有效的事情:ApacheSpark中的有效字符串匹配

    根据问题,您应尝试查找其他近似值以避免完整的笛卡尔积。

    如果要保留不匹配的数据,则可以跳过一个过滤器:

    (spark_df.alias("l")
        .crossJoin(spark_df.alias("r"))
        .where(levenshtein("l.word", "r.word") < 2)
        .groupBy("l.id", "l.word")
        .count()
        .withColumn("count", col("count") - 1))
    

    或(速度较慢,但​​通用性更高),请参考加入:

    (spark_df
        .select("id", "word")
        .distinct()
        .join(result, ["id", "word"], "left")
        .na.fill(0))
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看