如何在数组上使用提取

问题描述 投票:2回答:1

我有一个pyspark数据框,其中包含4列。我想从一列中提取一些字符串,其类型为Array of strings。我使用了regexp_extract函数,但由于regexp_extract仅接受字符串,因此返回了错误。

示例数据框:

id |  last_name | age | Identificator
------------------------------------------------------------------
12 | AA         | 23  |  "[""AZE","POI","76759","T86420","ADAPT"]"
------------------------------------------------------------------
24 | BB         | 24  | "[""SDN","34","35","AZE","21054","20126"]"
------------------------------------------------------------------

我想提取以下所有数字:

- contain 4, 5 or 6 digits
 - it should not attached to a letters.
 - if attached to letter Z ok, I should extract it.
 - save it in a new column in my Dataframe.

我开始这样做,但是由于标题是字符串数组,所以它不起作用。

expression = r'([0-9]){4,6}'
 df = df.withColumn("extract", F.regexp_extract(F.col("Identificator"), expression, 1))

如何使用regexp_extract或其他解决方案提取这些数字?谢谢

python regex pyspark
1个回答
2
投票

这是我可以使用SparkSQL 2.4.0 +内置函数filter

from pyspark.sql.functions import expr

df.withColumn('text_new', expr('filter(text, x -> x rlike "^Z?[0-9]{4,6}$")')) \
  .show(truncate=False)                                                                          
#+-----------------------------------+---------------------+
#|text                               |text_new             |
#+-----------------------------------+---------------------+
#|[AZE, POI, 76759, T86420, ADAPT]   |[76759]              |
#|[SDN, 34, Z8735, AZE, 21054, 20126]|[Z8735, 21054, 20126]|
#+-----------------------------------+---------------------+

结果是一个包含匹配项的数组。 regex ^Z?[0-9]{4,6}$匹配4-6位数字,可以选择在其后加上字符'Z'。

Edit:对于较早版本的Apache Spark,请使用udf()

import re
from pyspark.sql.functions import udf
from pyspark.sql.types import ArrayType, StringType

# regex pattern:
ptn = re.compile('^Z?[0-9]{4,6}$')

# create an udf to filter array
array_filter = udf(lambda arr: [ x for x in arr if re.match(ptn, x) ] if type(arr) is list else arr, ArrayType(StringType()))

df.withColumn('text_new', array_filter('text')) \
  .show(truncate=False)

Edit-2:根据您的注释,从'Z'到'MOD'并删除前导MOD,请使用lstrip()删除此子字符串。调整以下内容:

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()))
© www.soinside.com 2019 - 2024. All rights reserved.