在pyspark数据框的列中使用正则表达式捕获两个字符串之间的第一次出现的字符串

Posted

技术标签:

【中文标题】在pyspark数据框的列中使用正则表达式捕获两个字符串之间的第一次出现的字符串【英文标题】:Capturing first occurrence of a string between two strings using regex in a column in pyspark dataframe 【发布时间】:2020-12-06 07:43:35 【问题描述】:

我有一个 pyspark 数据框 (df),它有一个日期列(数据类型:str)和一个消息列(数据类型 str 使用 concat_ws() 从列表对象更改),如下所示:

示例数据框

Date               message
2020-11-01         ['some not required text1', 'Startstring ID :AB_CD', 
                   'some not required text2', 'ID :EDGH', 'some not 
                    required text3', 'ID :XYZ', 'Stopstring' 'some not 
                    required text4', 'Startstring ID :cd_ab', 'some not 
                    required text5', 'ID :ghed', 
                    'some not required text6', ID :zyx', 'Stopstring 'some 
                    not required text7']
2020-11-02         ['some not required text8', Startstring 'ID :ABCD', 
                   'some not required text9', 'ID :ED_GH', 'some not 
                    required text10', ID :X_YZ, Stopstring 'some not 
                    required text11', 'Startstring 
                    ID :cdab', 'some not required text12', 'ID :gh_ed', 
                    'some not required text13', ID :z_yx', 'Stopstring 
                    'some not required text14']

我希望在 ID 之后提取第一次出现的字符串:在 Startstring 和 Stopstring 之间,并丢弃不是第一次出现的 ID。一个日期可能有多个此类实例。

预期输出:

Date               message
2020-11-01         AB_CD 
2020-11-01         cd_ab
2020-11-02         ABCD 
2020-11-02         cdab

我尝试在 ID : as: 之后提取第一次出现的字符串:

import pyspark.sql.functions as F
from pyspark.sql.types import *

result = df.withColumn("message", F.regexp_extract(col("message"), r"Startstring[\s\S]*?ID :\s*(\S*)\b[\s\S]*? Stopstring",1))
result.show()

它只给了我紧跟在 ID : 之后的字符串,这是在特定日期的第一次,如下所示:

Date               message
2020-11-01         AB_CD 
2020-11-02         ABCD

非常感谢您提供这方面的帮助。谢谢

【问题讨论】:

【参考方案1】:

你可以做的是:

连接数组(如您所描述) 按“停止字符串”分割 explode the column 这意味着您会为数组的每个元素获得一行(因此对于每次出现的模式) 应用正则表达式。
df
  .withColumn("concat_message", F.concat_ws(" ",F.col("message")))
  .withColumn("split_message", F.split(F.col("concat_message"), "Stopstring"))
  .withColumn("exploded_message", F.explode(F.col("split_message")))
  .withColumn("parsed_ids", F.regexp_extract(F.col("exploded_message"), r"Startstring[\s\S]*?ID :\s*(\S*)\b[\s\S]*?",1))
  .filter(F.col("parsed_ids") != "")
  .show()

一个问题是,当通过“Stopmessage”分割时,这个词会从结果字符串中删除,并且不能在正则表达式模式中使用。

【讨论】:

感谢您的回答。在数据块上运行此脚本时出现错误。 “org.apache.spark.SparkException:作业因阶段故障而中止:阶段 100.0 中的任务 1 失败 4 次,最近一次失败:阶段 100.0 中丢失任务 1.3(TID 1425、10.139.64.5、执行程序 17):ExecutorLostFailure(执行程序17 由于其中一项正在运行的任务而退出)原因:远程 RPC 客户端已解除关联。可能是由于容器超出阈值或网络问题。请检查驱动程序日志以获取 WARN 消息。” 我解决了。您的代码提供了错误的答案。谢谢 您的错误消息听起来像是网络问题而不是代码问题...如果您认为提供的答案是错误的并找到了更好的解决方案,最好在这里分享,因为稍后参考。 是的,知道错误是由于网络问题。我解决了这个问题。但是,您的代码没有生成适当的输出。无论如何,我自己完成了代码。

以上是关于在pyspark数据框的列中使用正则表达式捕获两个字符串之间的第一次出现的字符串的主要内容,如果未能解决你的问题,请参考以下文章

pyspark:数据框在另一个数据框的列中按ID选择行

如何检查来自不同数据框的列值?

如何根据 PySpark 数据框的另一列中的值修改列? F.当边缘情况

从字符串 PySpark 数据框列中删除正则表达式

使用 pyspark 中的正则表达式将数字添加到字符串中最后一个字符之前的字符串

在 PySpark 中提取多个正则表达式匹配项