如何在PySpark DataFrame中新增列:仅提取含特定子串的内容
解决PySpark提取特定子串并生成新列的问题
可以通过PySpark的条件函数when/otherwise结合字符串处理函数实现需求,仅对包含指定子串的行提取目标内容,其余行新列值为null,不会过滤掉任何行。
方法一:使用substring_index(适合固定格式)
这种方法适用于ID格式固定为.../rule-id/目标值的场景,逻辑简单直接:
from pyspark.sql import functions as F # 生成新列 df2 = df1.withColumn( "rule-id", F.when( # 判断id列是否包含'rule-id'子串 F.instr(F.col("id"), "rule-id") > 0, # 提取'rule-id/'之后的所有内容 F.substring_index(F.col("id"), "rule-id/", -1) ).otherwise(F.lit(None)) # 不包含子串的行设为null )
代码说明:
instr(col, substr):返回子串在字符串中的起始位置,若不存在则返回0,以此判断是否包含目标子串。substring_index(col, delim, count):按分隔符分割字符串,count=-1表示取最后一个分隔符之后的部分。when(condition, value).otherwise(default):条件判断,满足条件时返回指定值,否则返回默认值(这里是null)。
方法二:使用正则表达式提取(适合灵活格式)
如果ID格式可能有变化,正则表达式的方式更灵活,能精准匹配目标内容:
from pyspark.sql import functions as F df2 = df1.withColumn( "rule-id", F.when( # 用正则判断是否包含'rule-id/'模式 F.col("id").rlike(r'rule-id/'), # 提取'rule-id/'之后到末尾的内容(无后续斜杠) F.regexp_extract(F.col("id"), r'rule-id/([^/]+)$', 1) ).otherwise(F.lit(None)) )
代码说明:
rlike(pattern):判断字符串是否匹配正则表达式,这里匹配包含rule-id/的行。regexp_extract(col, pattern, group):提取正则匹配的分组,pattern中的([^/]+)$表示捕获rule-id/之后到末尾、不含斜杠的内容,group=1表示取第一个捕获组的结果。
验证结果
运行上述代码后,你的DataFrame会生成预期的rule-id列:
+---------------------------------------+----------+---------+---------------+ |id |compliance|workflow |rule-id | +---------------------------------------+----------+---------+---------------+ |account/product/rule-id/r-1879bajhdfd80|PASS | NEW|r-1879bajhdfd80| |account/product/rule-id/r-198Hhfu89421s|PASS | NEW|r-198Hhfu89421s| |account/product/test/run/date/YYYYMMDD |FAIL | NEW|null | +---------------------------------------+----------+---------+---------------+
内容的提问来源于stack exchange,提问作者Danny
相关产品推荐
相关产品推荐

