【发布时间】:2020-02-24 13:58:28
【问题描述】:
我必须从数据框的列中提取一些代码,如下所示:
+---------+--------------------------------+--------------------+------+
|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 和 second),具体取决于 third 列是否包含星号。由于每一列中可以有多个代码,因此我需要一个数组中的所有正则表达式匹配项。在上面的例子中,我需要从first中提取AB12a,从second中提取[XYZ02, GFH11b]。
我发现默认的pyspark函数regexp_extract(https://issues.apache.org/jira/browse/SPARK-24884)不支持多个匹配,所以我定义了自己的regexp_extract_allUDF:
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)))
但是在使用 when 子句时,我得到了 TypeError: expected string or buffer:
# 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 进行稍微不同的定义。
有什么想法吗?
【问题讨论】:
-
我认为你应该使用 like("%*%") 而不是使用 like("*") Like THIS df = df.withColumn("code", when(col("third") .like("%*%"), udf_regexp_extract_all("second", lit(pattern))) .otherwise(udf_regexp_extract_all("first", lit(pattern))))
-
你说得对,我打错了。我在问题中对其进行了编辑,但这不是问题的根本原因。
-
你为我使用 bcoz 的 spark 版本吗 spark 2.4+ 在相同的代码上没有给出任何错误。并尝试从模式中删除 ^ 以将数据作为数组检索。
-
我正在运行 2.2.0,但问题是其中一列中可能存在空值。
-
因此,您能否在数据框中也使用 null 值来处理该错误
标签: python regex apache-spark pyspark user-defined-functions