如何将1行多列的PySpark DataFrame转置为多行2列结构?
PySpark 宽表转长表高效实现方案
针对你描述的1行多列(列名为JSON文件标识,列值为JSON内容)的PySpark DataFrame转置需求,以下是两种高效的纯代码实现方案:
方法一:使用stack SQL函数(推荐,性能最优)
stack是Spark SQL原生的宽转长函数,专门适配单行长表转多行列的场景,处理1000列完全无压力:
- 获取原DataFrame的所有列名:
cols = df.columns
- 自动拼接
stack表达式,生成列名与列值的对应关系:
# 构造stack语句格式:stack(列总数, '列名1', 列值1, '列名2', 列值2, ...) stack_expr = f"stack({len(cols)}, {', '.join([f'{repr(col)}, {col}' for col in cols])}) as (id, json_content)"
- 执行转换得到目标结构:
result_df = df.selectExpr(stack_expr)
方法二:自定义melt函数(通用型方案)
如果你习惯用melt逻辑,可以自定义实现兼容PySpark的melt函数,适配更复杂的宽转长场景:
from pyspark.sql.functions import create_map, explode, lit from pyspark.sql import DataFrame def melt(df: DataFrame, id_vars=None, value_vars=None, var_name="variable", value_name="value"): # 默认将所有列作为值列(无分组ID列) if id_vars is None: id_vars = [] if value_vars is None: value_vars = [col for col in df.columns if col not in id_vars] # 创建列名与列值的映射,通过explode展开为多行 map_col = create_map(*[lit(c), df[c] for c in value_vars]) return df.select(*id_vars, explode(map_col).alias(var_name, value_name)) # 调用函数并指定目标列名 result_df = melt(df, value_vars=df.columns, var_name="id", value_name="json_content")
方案说明
stack是Spark原生优化算子,列数较多时性能比自定义melt更优,优先推荐。- 两种方案均无需依赖外部工具,纯PySpark代码实现,避免了Excel转置的繁琐和性能瓶颈。
内容的提问来源于stack exchange,提问作者Antonius
相关产品推荐
相关产品推荐

