Pyspark: как работать с нулевыми значениями в пользовательских функциях Python - PullRequest
0 голосов
/ 07 мая 2019

Я хочу использовать некоторые функции схожести строк, которые не являются родными для pyspark, такие как меры jaro и jaro-winkler на фреймах данных.Они легко доступны в модулях Python, таких как jellyfish.Я могу написать pyspark udf's отлично для случаев, когда нет значений null, то есть, сравнивая кошку с собакой.когда я применяю эти udf к данным, где присутствуют значения null, это не работает.В таких задачах, как та, которую я решаю, очень часто одна из строк выглядит так: null

Мне нужна помощь, чтобы получить сходство строк в udf для работы в целом, чтобы быть более конкретным, чтобы работатьв случаях, когда одно из значений null

, я написал 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 значениями в данных, поскольку они работали, когда их не было.

Я изменил приведенную выше функцию, чтобы проверить, не являются ли оба значения нулевыми, и запускаю функцию, только если этоcase, в противном случае верните 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 голосов
/ 07 мая 2019

Мы немного изменим ваш код, и он должен нормально работать:

@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
...