我有一个pyspark数据框,我想改善正则表达式。 我想添加条件或将正则表达式修改为:
/
或letter
的所有号码。案例1的示例:
column_example | new_column
------------------------------------------------------|----------------- |
mundo por el número de NJU/LOK 12345T98789-hablantes | 12345
hispanohablantes ZES/UJ86758/L87586:residentes en | 86758
示例2:
列示例:
My_column | new_column
------------------------------------------------------|---------------------
mundo por el número de ABC 8567 hablantes | []
------------------------------------------------------|---------------------
con dominio nativo ABC 987480 millones de personas | []
------------------------------------------------------|---------------------
hispanohablantes residentes en ABC98754 otros países | []
以下代码是:
ptn = re.complie(r'^(?:MOD)?[0-9]{4,6}$')
array_filter = udf(lambda arr: [ x.lstrip('MOD') for x in arr if re.match(ptn, x) ] if type(arr) is list else arr, ArrayType(StringType()))
我该怎么办? 谢谢
答案 0 :(得分:2)
在版本 2.4.0 之前不使用udf
的Spark的一种方法:
from pyspark.sql.functions import split, regexp_replace
df.withColumn('new_column'
, split(
regexp_replace(
regexp_replace('My_column', r'.*?(?<!ABC\s{0,5})(?<!\d)(\d{4,6})(?=[A-Z/])', '$1\0')
, '\0?[^\0]*$'
, ''
)
,'\0')
) \
.show(truncate=False)
+-----------------------------------------------------------------------+--------------+
|My_column |new_column |
+-----------------------------------------------------------------------+--------------+
|23458/ mundo por el nmero de NJU/LOK 12345T98789 hablantes |[23458, 12345]|
|con dominio nativo ABC 987480 millones ZES/UJ86758/L87586:residentes en|[86758] |
|hispanohablantes residentes en ABC98754/ otros pases |[] |
+-----------------------------------------------------------------------+--------------+
位置:
使用regexp_replace:替换与以下模式匹配的文本
.*?(?<!ABC\s{0,5})(?<!\d)(\d{4,6})(?=[A-Z/])
带有$1\0
,可删除 NUMBER_NEEDED 之前的所有无关文本(保存在 $ 1 中),该文本之前不包含ABC\s{0,5}
和{{1} },但后跟\d
。在每个匹配的[A-Z/]
的末尾放置一个NULL char \0
。
使用$1
将上述文本转换为数组,请注意,数组的最后一项无关紧要,应排除在外
使用另一个split(text, '\0')
删除结尾的不相关文本,然后再运行上述 split()函数
注释:
regexp_replace(text, '\0?[^\0]*$', '')
将允许测试(?<!ABC\s{0,5})
和 NUMBER_NEEDED 之间的0-5空格。由于正则表达式负向后搜索不支持ABC
,因此,如果文本之间可能包含更多空格,则可以将(?<!ABC\s*)
调整为更大的数字。顺便说一句。 5
适用于PySpark,但在Python (?<!ABC\s{0,5})
模块中无效,该模块仅允许使用固定宽度的模式
在re
之前加上(?s)
,以允许点号模式(如果任何文本包含换行符)
我假定您的原始文本中未显示NULL char \0
,因为它不是匹配项的一部分,因此您可以在运行上述3个字符之前将其全部删除(regexp_replace(text, '\0', '')
)功能。
import re
from pyspark.sql.types import ArrayType, StringType
from pyspark.sql.functions import udf
ptn = re.compile(r'(?<!ABC)(?<!\d)(\d{4,6})(?=[A-Z/])')
find_number = udf(lambda x: re.findall(ptn, re.sub(r'(?<=ABC)\s+', '', x)) if x else [], ArrayType(StringType()))
df.withColumn('new_column', find_number('My_column')).show()