Мне нужно извлечь некоторые коды из столбцов кадра данных, который выглядит следующим образом:
+---------+--------------------------------+--------------------+------+
|first |second |third |num |
+---------+--------------------------------+--------------------+------+
|AB12a |xxxxxx |some other data |100000|
|yyyyyyy |XYZ02, but possibly also GFH11b |Look at second col* |120000|
+---------+--------------------------------+--------------------+------+
Коды следуют регулярному выражению "^([A-Z]+[0-9]+[a-z]*)"
и разбросаны по двум столбцам (first
и * 1006). *) в зависимости от того, содержит ли звездочка third
. Поскольку в каждом столбце может быть несколько кодов, мне нужны все совпадения регулярных выражений в массиве. В приведенном выше примере мне нужно извлечь AB12a
из first
и [XYZ02, GFH11b]
из second
.
Я обнаружил, что множественные совпадения не поддерживаются функцией pyspark по умолчанию regexp_extract
(https://issues.apache.org/jira/browse/SPARK-24884), поэтому я определил свой собственный regexp_extract_all
UDF:
from pyspark.sql.types import *
from pyspark.sql.functions import *
import re
def regexp_extract_all(s, pattern):
pattern = re.compile(pattern, re.M)
all_matches = re.findall(pattern, s)
return all_matches
pattern = "^([A-Z]+[0-9]+[a-z]*)"
udf_regexp_extract_all = udf(regexp_extract_all, ArrayType(StringType()))
Мне удалось заставить работать UDF, если применить его к каждому столбцу отдельно:
# this extracts AB12a from first
df = df.withColumn("code", udf_regexp_extract_all("first", lit(pattern)))
# this extracts [XYZ02, GFH11b] from second
df = df.withColumn("code", udf_regexp_extract_all("second", lit(pattern)))
Но я получаю TypeError: expected string or buffer
при работе в предложении when:
# this gives at runtime TypeError: expected string or buffer
df = df.withColumn("code", when(col("third").like("%*%"),
udf_regexp_extract_all("second", lit(pattern)))
.otherwise(udf_regexp_extract_all("first", lit(pattern))))
Я думаю, что, вероятно, меня заваливают типами во время выполнения, потому что что-то происходит в предложении when, для которого нужно определить мой UDFнемного по-другому.
Есть идеи?