使用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
相关产品推荐
相关产品推荐

