PySpark如何筛选DataFrame中名称为列表元素子串的行?
解决PySpark中按子串匹配筛选DataFrame的问题
问题背景
给定PySpark DataFrame:
df = spark.createDataFrame( [ (43431, "Urban Philosophy"), (53432, "Fix Guru"), (63433, "Evergrow") ], ["id", "name"] )
以及名称列表:
name_list=['Urban Philosophy Inc.', 'Limited Fix Guru Holdings', 'Contractors Supply Co.', 'Evergrow LLC']
需求是筛选出df中name列的值是name_list某一元素子串的行,原代码使用isin无法实现,因为isin仅支持精确匹配。
解决方案
方法1:构造OR连接的包含条件
直接遍历name_list,构造多个「判断列表元素是否包含DataFrame中name值」的条件,用OR逻辑连接:
from pyspark.sql.functions import col, lit # 初始化条件为False match_condition = lit(False) for target_name in name_list: # 每个条件:判断当前列表元素是否包含df的name值 match_condition = match_condition | lit(target_name).contains(col("name")) # 筛选符合条件的行 filtered_df = df.filter(match_condition)
方法2:广播变量+UDF(适合大列表场景)
如果name_list数据量较大,使用广播变量将列表分发到各节点,配合UDF提升性能:
from pyspark.sql.functions import udf, broadcast from pyspark.sql.types import BooleanType # 广播名称列表到所有节点 broadcast_names = broadcast(sc.broadcast(name_list)) # 定义UDF:检查当前name是否是列表中某元素的子串 def check_substring(name): return any(name in item for item in broadcast_names.value) substring_check_udf = udf(check_substring, BooleanType()) # 执行筛选 filtered_df = df.filter(substring_check_udf(col("name")))
原代码错误说明
原代码中col('name').isin(x)存在两个问题:
isin接收的是列表参数,传入单个字符串时等价于精确匹配当前字符串,而非子串判断- 逻辑方向错误:需要判断列表元素是否包含DataFrame的name值,而非name值是否在某个字符串的字符列表中
内容的提问来源于stack exchange,提问作者Olgaraa
相关产品推荐
相关产品推荐

