我想使用一些不是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 |
+-----------+------------+------------------+
答案 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