在PySpark 2.4中用findall提取列字符串并创建数组列
PySpark 2.4 提取「标签:内容:」格式字符串生成数组列
问题根源
你用re.findall配合UDF提取时返回元组数组,是因为正则表达式中使用了捕获分组,导致每个匹配结果被拆分为元组(比如分组捕获标签和内容两部分)。要得到完整的「标签:内容:」字符串数组,可通过以下两种方式修正:
方法1:修改正则表达式,避免捕获分组
直接匹配整个「标签:内容:」格式的字符串,不使用分组,这样re.findall会直接返回字符串数组。
示例代码:
import re from pyspark.sql.functions import udf, col from pyspark.sql.types import ArrayType, StringType def extract_tags(s): if not s: return [] # 匹配完整的「标签:内容:」串,根据实际标签格式调整正则 # 此处假设标签为2位字母/数字开头,可按需修改 pattern = r'[A-Z0-9]{2,}:.*?:' return re.findall(pattern, s) # 注册UDF extract_tags_udf = udf(extract_tags, ArrayType(StringType())) # 生成目标数组列 df = df.withColumn("extracted_tags", extract_tags_udf(col("main_block")))
说明:
.*?是非贪婪匹配,确保只匹配到单个「标签:内容:」单元,避免跨单元匹配。如果标签格式有固定规则(比如必须是2位数字+1位字母),可把正则更改为\d{2}[A-Z]:.*?:以提升匹配精度。
方法2:保留原正则,拼接元组为目标字符串
如果不想修改原有正则,可在UDF中将匹配得到的元组拼接成「标签:内容:」格式的字符串。
示例代码:
import re from pyspark.sql.functions import udf, col from pyspark.sql.types import ArrayType, StringType def extract_tags(s): if not s: return [] # 原带分组的正则 pattern = r'([A-Z0-9]{2,}):(.*?):' matches = re.findall(pattern, s) # 将每个元组拼接为目标格式字符串 return [f"{tag}:{content}:" for tag, content in matches] extract_tags_udf = udf(extract_tags, ArrayType(StringType())) df = df.withColumn("extracted_tags", extract_tags_udf(col("main_block")))
验证效果
假设main_block列的内容为:
"20C:SEME//123/1XXXXXX:23G:NEWM:20A:TEST1//111/1XXXXXX:20A:TEST2:19A:TEST3:22B:ABC//777/1XXXXXX:20C:TESTB:19A:SETT//USD65548,33:"
处理后extracted_tags列会生成如下数组:
["20C:SEME//123/1XXXXXX:", "23G:NEWM:", "20A:TEST1//111/1XXXXXX:", "20A:TEST2:", "19A:TEST3:", "22B:ABC//777/1XXXXXX:", "20C:TESTB:", "19A:SETT//USD65548,33:"]
内容的提问来源于stack exchange,提问作者kmr
相关产品推荐
相关产品推荐

