通过正则表达式捕获组拆分 spark 数据框列中的字符串

新手上路,请多包涵

给定以下数据框,我想将数字列拆分为数组中原始数字的每个元素 3 个字符的数组

给定数据框:

 +---+------------------+
| id|           numbers|
+---+------------------+
|742|         000000000|
|744|            000000|
|746|003000000000000000|
+---+------------------+

预期数据框:

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

我在使用下面给出的 split 函数时尝试了不同的正则表达式,我认为应该在第一次尝试时使用正则表达式:

 import pyspark.sql.functions as f

df = spark.createDataFrame(
    [
        [742, '000000000'],
        [744, '000000'],
        [746, '003000000000000000'],
    ],
    ["id", "numbers"]
)

df = df.withColumn("numbers", f.split("numbers", "[0-9]{3}"))

df.show()

然而结果是

+---+--------------+
| id|       numbers|
+---+--------------+
|742|      [, , , ]|
|744|        [, , ]|
|746|[, , , , , , ]|
+---+--------------+

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

原文由 Shadab Shariff 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

以下是如何在不使用 udf 的情况下执行此操作:

 df = df.withColumn(
    "numbers",
    f.split(f.regexp_replace("numbers", "([0-9]{3})(?!$)", r"$1,"), ",")
)

df.show(truncate=False)
#+---+------------------------------+
#|id |numbers                       |
#+---+------------------------------+
#|742|[000, 000, 000]               |
#|744|[000, 000]                    |
#|746|[003, 000, 000, 000, 000, 000]|
#+---+------------------------------+

首先使用 pyspark.sql.functions.regexp_replace 将 3 位数字的序列替换为后跟逗号的序列。然后用逗号分割结果字符串。

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

在匹配模式中,我们还包括对字符串结尾的否定前瞻, (?!$) ,以避免在字符串结尾添加逗号。

参考: REGEXP_REPLACE 捕获组

原文由 pault 发布,翻译遵循 CC BY-SA 4.0 许可协议

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

 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)

原文由 Psidom 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进