You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PySpark中基于数值列筛选列表列数据:保留超集及列值大于其超集的子集

解决PySpark DataFrame的超集/子集筛选问题

这个需求挺清晰的,我来一步步帮你实现!首先明确我们要保留两类行:

  • 所有超集行:即没有其他列表能完全包含当前行的column a的行
  • 符合条件的子集行:当前行的column a是某个超集的子集,且它的column b值大于该超集的column b值

第一步:创建示例输入DataFrame

先把你给出的示例数据转换成PySpark DataFrame,方便后续测试:

from pyspark.sql import SparkSession
from pyspark.sql import functions as F

spark = SparkSession.builder.appName("subset_superset_filter").getOrCreate()

# 输入数据
data = [
    (["A", "B", "C"], 10),
    (["A", "C"], 15),
    (["B", "C"], 7),
    (["J", "S", "K"], 8),
    (["J", "S"], 9),
    (["J", "K"], 8)
]

df = spark.createDataFrame(data, schema=["a", "b"])
df.show(truncate=False)

运行后会得到你的输入DataFrame:

+---------+---+
|a        |b  |
+---------+---+
|[A,B,C]  |10 |
|[A,C]    |15 |
|[B,C]    |7  |
|[J,S,K]  |8  |
|[J,S]    |9  |
|[J,K]    |8  |
+---------+---+

第二步:找出所有子集-超集对应关系

我们通过自连接DataFrame,找出所有子集和其对应的超集(即列表被完全包含且长度更短的行):

# 自连接,匹配子集和超集
subset_superset_pairs = df.alias("subset").join(
    df.alias("superset"),
    # 判断条件:subset的列表是superset的子集,且长度更小(避免自己匹配自己)
    F.expr("size(subset.a) < size(superset.a) AND array_except(subset.a, superset.a) == array()")
).select(
    F.col("subset.a").alias("subset_a"),
    F.col("subset.b").alias("subset_b"),
    F.col("superset.b").alias("superset_b")
)

subset_superset_pairs.show(truncate=False)

这一步会得到所有符合子集-超集关系的配对:

+--------+---------+----------+
|subset_a|subset_b |superset_b|
+--------+---------+----------+
|[A,C]   |15       |10        |
|[B,C]   |7        |10        |
|[J,S]   |9        |8         |
|[J,K]   |8        |8         |
+--------+---------+----------+

第三步:筛选符合条件的子集行

从上面的配对中,筛选出subset_b大于superset_b的子集行,并且去重(避免同一个子集对应多个超集时重复保留):

# 筛选有效子集行:subset_b > superset_b
valid_subsets = subset_superset_pairs.filter(
    F.col("subset_b") > F.col("superset_b")
).select("subset_a", "subset_b").withColumnRenamed("subset_a", "a").withColumnRenamed("subset_b", "b").distinct()

valid_subsets.show(truncate=False)

运行后得到有效的子集行:

+-------+---+
|a      |b  |
+-------+---+
|[A,C]  |15 |
|[J,S]  |9  |
+-------+---+

第四步:筛选所有超集行

超集行是指没有任何其他列表能完全包含它的行,我们可以通过判断是否存在更大的超集来筛选:

# 筛选超集行:不存在其他行的列表包含当前行的列表且长度更长
superset_rows = df.filter(
    F.expr("NOT EXISTS (SELECT 1 FROM df other WHERE size(other.a) > size(a) AND array_except(a, other.a) == array())")
)

superset_rows.show(truncate=False)

得到的超集行:

+---------+---+
|a        |b  |
+---------+---+
|[A,B,C]  |10 |
|[J,S,K]  |8  |
+---------+---+

第五步:合并结果

最后把超集行和有效子集行合并,去重后就是我们需要的最终结果:

# 合并超集行和有效子集行
final_result = superset_rows.union(valid_subsets).distinct()
final_result.show(truncate=False)

最终输出和你预期的一致:

+---------+---+
|a        |b  |
+---------+---+
|[A,B,C]  |10 |
|[A,C]    |15 |
|[J,S,K]  |8  |
|[J,S]    |9  |
+---------+---+

补充说明

  • 如果一个子集对应多个超集,只要其中一个超集的b值小于它的b值,就会被保留
  • 用array_except判断子集关系是PySpark中比较简洁的方式,确保子集的所有元素都在超集中
  • 整个流程都是基于PySpark的原生函数,适合处理大数据量的场景

内容的提问来源于stack exchange,提问作者Sandhyalakshmi K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 02:09:05