PySpark:基于列表值过滤DataFrame,排除含指定代码的记录
从Spark DataFrame中排除包含指定编码的记录
问题背景
给定编码列表 codes = ['O30', 'O81', 'Z38'],需要从Spark DataFrame中移除所有codelist字段包含该列表中任意编码的记录。现有DataFrame结构及数据如下:
codes = ['O30', 'O81', 'Z38'] from pyspark.sql.types import StructType,StructField, StringType, IntegerType dfrows = [ ("Jane", "Doe", "I13; Z22; F11"), ("Janet", "Doser", "O81; F22; I11"), ("Jean", "Dew", "D11; O30; Z00; D10"), ("Janey", "Doedoe", "D11; Z38; Z00; O81"), ("Jena", "Dote", "I13"), ("Jenae", "Dee", "O30") ] schema = StructType([ \ StructField("fakefirstname",StringType(),True), \ StructField("fakelastname",StringType(),True), \ StructField("codelist", StringType(), True) ]) scdf = sc.createDataFrame(data=dfrows ,schema=schema)
预期结果仅保留不包含目标编码的记录:
+-------------+------------+-------------+ |fakefirstname|fakelastname| codelist| +-------------+------------+-------------+ | Jane| Doe|I13; Z22; F11| | Jena| Dote| I13| +-------------+------------+-------------+
解决方案
方法一:正则表达式精准匹配
利用正则匹配独立的目标编码(避免误匹配包含目标编码的其他字符),通过取反过滤掉符合条件的记录:
from pyspark.sql import functions as F # 构建正则:覆盖编码在开头、中间、结尾的所有情况 pattern = r"(^|; )(" + "|".join(codes) + ")(; |$)" filtered_df = scdf.filter(~F.regexp_like(scdf.codelist, pattern)) filtered_df.show()
正则逻辑:
(^|; ):匹配编码的前缀(字符串开头或分号加空格)(O30|O81|Z38):匹配目标编码列表中的任意一个(; |$):匹配编码的后缀(分号加空格或字符串结尾)
方法二:数组交集检查
将codelist拆分为数组后,检查与目标编码列表是否存在交集,无交集则保留记录:
from pyspark.sql import functions as F # 拆分编码字符串为数组,计算与目标编码的交集,无交集则保留 filtered_df = scdf.filter( F.size(F.array_intersect(F.split(scdf.codelist, "; "), F.lit(codes))) == 0 ) filtered_df.show()
逻辑说明:
split(scdf.codelist, "; "):将分号分隔的字符串转为编码数组array_intersect(...):计算拆分后的数组与目标编码数组的交集size(...) == 0:交集长度为0表示当前记录不包含任何目标编码,予以保留
内容的提问来源于stack exchange,提问作者bshelt141
相关产品推荐
相关产品推荐

