Pyspark:如何处理python用户定义函数中的空值

时间:2019-05-07 15:16:21

标签: python apache-spark pyspark apache-spark-sql similarity

我想使用一些不是pyspark固有的字符串相似性函数,例如数据帧上的jaro和jaro-winkler度量。这些在python模块(例如jellyfish)中很容易获得。对于没有null值的情况(即猫与狗比较),我可以写pyspark udf很好。当我将这些udf应用于存在null值的数据时,它将不起作用。在诸如我要解决的问题中,其中一个字符串通常为null

我需要帮助使我的字符串相似度udf正常工作,更具体地说,在其中一个值为null的情况下工作

我编写了一个udf,当输入数据中没有空值时,该udf可以工作:

from pyspark.sql.functions import udf
from pyspark.sql.types import DoubleType
import pyspark.sql.functions as F
import jellyfish.cjellyfish

def jaro_winkler_func(df, column_left, column_right):

    jaro_winkler_udf = udf(f=lambda s1, s2: jellyfish.jaro_winkler(s1, s2), returnType=DoubleType())

    df = (df
          .withColumn('test',
                      jaro_winkler_udf(df[column_left], df[column_right])))

    return df

示例输入和输出:

+-----------+------------+
|string_left|string_right|
+-----------+------------+
|       dude|         dud|
|       spud|         dud|
+-----------+------------+
+-----------+------------+------------------+
|string_left|string_right|              test|
+-----------+------------+------------------+
|       dude|         dud|0.9166666666666666|
|       spud|         dud|0.7222222222222222|
+-----------+------------+------------------+

当我对具有空值的数据运行此命令时,会得到通常的火花错误,似乎最适用的是TypeError: str argument expected。我认为这是由于数据中的null值所致,因为当没有值时它就起作用了。

我修改了上面的函数以检查两个值是否都不为null,仅在这种情况下才运行该函数,否则返回0。

from pyspark.sql.functions import udf
from pyspark.sql.types import DoubleType
import pyspark.sql.functions as F
import jellyfish.cjellyfish

def jaro_winkler_func(df, column_left, column_right):

    jaro_winkler_udf = udf(f=lambda s1, s2: jellyfish.jaro_winkler(s1, s2), returnType=DoubleType())

    df = (df
       .withColumn('test',
                   F.when(df[column_left].isNotNull() & df[column_right].isNotNull(),
                          jaro_winkler_udf(df[column_left], df[column_right]))
                   .otherwise(0.0)))

    return df

但是,我仍然遇到与以前相同的错误。

样本输入以及我想要的输出是什么

+-----------+------------+
|string_left|string_right|
+-----------+------------+
|       dude|         dud|
|       spud|         dud|
|       spud|        null|
|       null|        null|
+-----------+------------+
+-----------+------------+------------------+
|string_left|string_right|              test|
+-----------+------------+------------------+
|       dude|         dud|0.9166666666666666|
|       spud|         dud|0.7222222222222222|
|       spud|        null|0.0               |
|       null|        null|0.0               |
+-----------+------------+------------------+

1 个答案:

答案 0 :(得分:0)

我们将修改您的代码一点,它应该可以正常工作:

@udf(DoubleType())
def jaro_winkler(s1, s2):
    if not all((s1,s2)):
        out = 0
    else: 
        out = jellyfish.jaro_winkler(s1, s2)
    return out


def jaro_winkler_func(df, column_left, column_right):

    df = df.withColumn(
        'test',
        jaro_winkler(df[column_left], df[column_right]))
    )

    return df