如何在PySpark中转置DataFrame并实现布尔值统计转换(不使用Pandas)
如何在PySpark中转置DataFrame并统计布尔值数量?
针对你的需求,我来一步步拆解解决——先聊聊通用的DataFrame转置思路,再针对你给出的布尔值统计场景给出具体实现。
一、通用的PySpark DataFrame转置方法
PySpark没有内置的transpose()函数,所以得靠组合现有函数实现,核心逻辑是把列转换成行,常见的两种思路:
create_map+explode组合:适合聚合后的统计结果转置(比如你的案例),把列名和对应统计值映射成键值对再展开- 行号标记 +
melt+pivot:适合纯行列互换(比如把每行数据转成列、每列转成行)
你的需求属于带统计的转置,我们重点看这种场景的实现。
二、针对布尔值统计转置的具体实现
你的目标是把原DataFrame的每一列转成结果的一行,同时统计该列中TRUE和FALSE的数量,分三步完成:
步骤1:复现你的原始DataFrame
先把你给出的数据转换成PySpark DataFrame:
from pyspark.sql import SparkSession from pyspark.sql.functions import col, sum, when, lit, explode, create_map, struct spark = SparkSession.builder.appName("BooleanTranspose").getOrCreate() # 你的原始数据 data = [ (True, False, True), (True, False, False), (True, True, True), (True, True, False), (True, False, True) ] df = spark.createDataFrame(data, ["col1", "col2", "col3"]) df.show()
运行后会输出你的原始结构:
+----+-----+-----+ |col1| col2| col3| +----+-----+-----+ |true|false| true| |true|false|false| |true| true| true| |true| true|false| |true|false| true| +----+-----+-----+
步骤2:统计每列的TRUE/FALSE数量
用sum(when(...))对每列分别统计TRUE和FALSE的个数,这里用循环动态生成表达式,避免重复手写:
# 获取所有列名 columns = df.columns # 动态生成统计表达式 stat_expressions = [] for col_name in columns: # 统计TRUE的数量 stat_expressions.append(sum(when(col(col_name) == True, 1).otherwise(0)).alias(f"{col_name}_TRUE")) # 统计FALSE的数量 stat_expressions.append(sum(when(col(col_name) == False, 1).otherwise(0)).alias(f"{col_name}_FALSE")) # 计算统计结果 stats_df = df.select(*stat_expressions) stats_df.show()
这一步会得到一行的统计结果:
+--------+---------+--------+---------+--------+---------+ |col1_TRUE|col1_FALSE|col2_TRUE|col2_FALSE|col3_TRUE|col3_FALSE| +--------+---------+--------+---------+--------+---------+ | 5| 0| 2| 3| 3| 2| +--------+---------+--------+---------+--------+---------+
步骤3:转置统计结果
用create_map把每个原列的两个统计值打包成结构,再用explode展开成行:
# 动态生成映射关系:列名 -> (TRUE计数, FALSE计数) map_entries = [] for col_name in columns: map_entries.append(lit(col_name)) map_entries.append(struct(col(f"{col_name}_TRUE").alias("TRUE"), col(f"{col_name}_FALSE").alias("FALSE"))) # 转置并展开结构 transposed_df = stats_df.select( explode(create_map(*map_entries)).alias("x", "values") ).select("x", "values.TRUE", "values.FALSE") transposed_df.show()
运行后就得到了你想要的最终结果:
+----+----+-----+ | x|TRUE|FALSE| +----+----+-----+ |col1| 5| 0| |col2| 2| 3| |col3| 3| 2| +----+----+-----+
补充说明
全程用PySpark原生函数实现,避免了把数据拉到Driver端(Pandas会加载到本地内存),更适合大数据量场景。如果你的列数固定,也可以手动写映射关系,但动态生成的方式更通用,新增列时不需要修改代码。
内容的提问来源于stack exchange,提问作者Alejandro Montenegro
相关产品推荐
相关产品推荐

