Python 3.x 通过捕获组的正则表达式拆分spark dataframe列中的字符串

Python 3.x 通过捕获组的正则表达式拆分spark dataframe列中的字符串,python-3.x,apache-spark,pyspark,apache-spark-sql,Python 3.x,Apache Spark,Pyspark,Apache Spark Sql,给定下面的数据帧,我想将numbers列拆分为一个数组,数组中原始数字的每个元素包含3个字符 给定数据帧: +---+------------------+ |身份证号码| +---+------------------+ |742| 000000000| |744| 000000| |746|003000000000000000| +---+------------------+ 预期数据帧: +---+-------------------------

给定下面的数据帧,我想将numbers列拆分为一个数组,数组中原始数字的每个元素包含3个字符

给定数据帧:

+---+------------------+
|身份证号码|
+---+------------------+
|742|         000000000|
|744|            000000|
|746|003000000000000000|
+---+------------------+
预期数据帧:

+---+----------------------------------+
|身份证号码|
+---+----------------------------------+
|742| [000, 000, 000]                  |
|744| [000, 000]                       |
|746| [003, 000, 000, 000, 000, 000]   |
+---+----------------------------------+
我在使用下面给出的
split
函数和正则表达式时尝试了不同的正则表达式,我觉得在第一次尝试时就应该使用正则表达式:

导入pyspark.sql.f函数
df=spark.createDataFrame(
[
[742, '000000000'], 
[744, '000000'], 
[746, '003000000000000000'], 
],
[“id”,“数字”]
)
df=df.withColumn(“数字”,f.split(“数字”,“0-9]{3}”))
df.show()
然而,结果是

+---+--------------+
|身份证号码|
+---+--------------+
|742|      [, , ]|
|744|        [, ]|
|746|[, , , ]|
+---+--------------+

我想知道我做错了什么。是否有可能设置全局标志以获取所有匹配项,或者我是否完全遗漏了正则表达式中的某些内容?

split
将删除字符串拆分的模式;您需要为此创建一个自定义项:

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

# create a udf with re.findall
split_by_three = f.udf(lambda s: re.findall(r'\d{3}', s), ArrayType(StringType()))
df.withColumn('numbers', split_by_three('numbers')).show(3, False)

#+---+------------------------------+
#|id |numbers                       |
#+---+------------------------------+
#|742|[000, 000, 000]               |
#|744|[000, 000]                    |
#|746|[003, 000, 000, 000, 000, 000]|
#+---+------------------------------+

df.withColumn('numbers', split_by_three('numbers')).printSchema()
#root
# |-- id: long (nullable = true)
# |-- numbers: array (nullable = true)
# |    |-- element: string (containsNull = true)

以下是不使用
udf
的方法:

df=df.withColumn(
“数字”,
f、 split(f.regexp_replace(“数字”),“([0-9]{3})(?!$)”,r“$1,”,“,”)
)
df.show(truncate=False)
#+---+------------------------------+
#|身份证号码|
#+---+------------------------------+
#|742|[000, 000, 000]               |
#|744|[000, 000]                    |
#|746|[003, 000, 000, 000, 000, 000]|
#+---+------------------------------+
首先使用后跟逗号的序列替换3位数字的序列。然后在逗号上拆分结果字符串

替换模式
“$1”
表示第一个捕获组,后跟逗号

在匹配模式中,我们还为字符串结尾添加了一个负的前瞻性,
(?!$)
,以避免在字符串结尾添加逗号


参考资料:

两种@pault和@Psidom方法都很棒!这是另一种选择

>>> split_udf = F.udf(lambda x: ','.join([''.join(i) for i in zip(*[iter(x)]*3)]))
>>> df.withColumn('numbers', F.split(split_udf('numbers'),',')).show(truncate=False)
+---+------------------------------+
|id |numbers                       |
+---+------------------------------+
|742|[000, 000, 000]               |
|744|[000, 000]                    |
|746|[003, 000, 000, 000, 000, 000]|
+---+------------------------------+

每当我看到你需要为此创建一个自定义项时,我就把它当作一个个人挑战。这非常聪明-@Psidom的一个缺点是它假设字符串中不存在其他逗号。