You need to enable JavaScript to run this app. 使用PySpark合并DataFrame两列并统计非空值的出现次数
优惠活动
大模型
产品
解决方案
定价
更多

使用PySpark合并DataFrame两列并统计非空值的出现次数

Spark 双列合并值频次统计实现

核心流程分三步:将name1/name2两列纵向拼接为单列、过滤空值(含空字符串/纯空白/Null)、分组统计每个值的出现频次,两种常用实现方式均可得到预期结果:

实现方式1:用stack函数转长表(推荐)

该方式单次扫描原表,性能优于多次union的写法,代码如下:

from pyspark.sql import functions as F

# 宽转长,将name1、name2列统一转换为name列
merged_name_df = df.select(
    F.stack(2, "name1", "name2").alias("name")
)

# 过滤所有无效值:空字符串、纯空白串、None值
valid_name_df = merged_name_df.filter(
    F.trim(F.col("name")) != "",
    F.col("name").isNotNull()
)

# 分组计数,对齐预期输出的列名
occurrence_df = valid_name_df.groupBy("name").agg(
    F.count("*").alias("Occurrence")
)

# 结果验证输出
occurrence_df.show()

实现方式2:用unionByName纵向合并列

采用显式列合并的写法,逻辑和上面完全等价:

from pyspark.sql import functions as F

# 分别取出两列,重命名为统一列名
name1_col = df.select("name1").withColumnRenamed("name1", "name")
name2_col = df.select("name2").withColumnRenamed("name2", "name")

# 纵向合并两列数据
merged_name_df = name1_col.unionByName(name2_col)

# 后续过滤、计数逻辑和方式1一致
occurrence_df = merged_name_df.filter(
    F.trim(F.col("name")) != "",
    F.col("name").isNotNull()
).groupBy("name").agg(
    F.count("*").alias("Occurrence")
)

注意:过滤条件中加F.trim()是为了覆盖带空格的伪空值(比如全是空格的字符串),比直接判断!= ""更贴合空值过滤要求,测试数据中最后一行的空字符串会被直接过滤,不会计入统计。
两种方式运行后输出的计数结果和预期完全匹配:

+------------------+----------+
|name              |Occurrence|
+------------------+----------+
|Jeanny  Thorn     |3         |
|Luc  Krier        |2         |
|Meindert I Tholen |2         |
|Ben Weller        |1         |
|Liam Muller       |1         |
|Teddy E Beecher   |1         |
|Philippe  Schauss |1         |
+------------------+----------+

内容的提问来源于stack exchange,提问作者John Doe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.08 11:27:04