如何基于字符串是否在列表中实现PySpark DataFrame关联
在PySpark中基于字符串是否存在于列表列关联两个DataFrame
我来帮你搞定这个关联需求~ 你要的是把DataFrame A里的Name字符串,和DataFrame B里的NamesList列表做匹配,找出所有Name存在于NamesList中的配对,下面是具体的实现步骤和代码:
先准备示例数据
首先我们先把你给出的示例DataFrame创建出来,方便后续测试:
from pyspark.sql import SparkSession from pyspark.sql.functions import array_contains # 初始化Spark会话 spark = SparkSession.builder.appName("StringInListJoin").getOrCreate() # 创建DataFrame A data_a = [(1, "George"), (2, "Sarah")] df_a = spark.createDataFrame(data_a, ["Id", "Name"]) # 创建DataFrame B data_b = [(6, ["Bob", "Alice", "Sarah"]), (7, ["Tom", "George", "Emma"])] df_b = spark.createDataFrame(data_b, ["Id2", "NamesList"])
方法1:直接用Join配合array_contains条件(推荐)
Spark内置了array_contains函数,专门用来判断元素是否在数组列里。我们可以直接把这个判断作为Join的条件,这样既能得到匹配结果,性能也更优:
# 执行关联,用inner join只保留互相匹配的行 result_df = df_a.join(df_b, array_contains(df_b.NamesList, df_a.Name), "inner") # 查看结果 result_df.show()
运行后会得到你想要的匹配结果:
+---+-----+---+--------------------+ | Id| Name|Id2| NamesList| +---+-----+---+--------------------+ | 1|George| 7|[Tom, George, Emma]| | 2| Sarah| 6|[Bob, Alice, Sarah]| +---+-----+---+--------------------+
方法2:交叉连接后过滤(适合复杂逻辑)
如果你的匹配逻辑后续需要扩展,也可以先做笛卡尔积(交叉连接),再过滤符合条件的行。不过注意,这种方法在数据量大的时候性能会差一些,因为会先生成所有可能的配对:
# 先做交叉连接生成所有配对 cross_df = df_a.crossJoin(df_b) # 过滤出Name在NamesList里的行 result_df = cross_df.filter(array_contains(cross_df.NamesList, cross_df.Name)) result_df.show()
这个方法的结果和方法1完全一致,只是中间过程不同。
额外小提示
array_contains的参数顺序别搞反哦:第一个参数是数组列,第二个是要查找的元素。- 如果需要保留A中没有匹配的行(或者B中没有匹配的行),可以把Join类型改成
left、right或者outer,比如df_a.join(df_b, ..., "left")会保留A的所有行,匹配不到B的话B的列会显示null。
内容的提问来源于stack exchange,提问作者bettaberg
相关产品推荐
相关产品推荐

