在Databricks(Python 2)中翻转单行多列PySpark DataFrame
解决PySpark DataFrame一行多列转两行列名-值对的问题
刚好遇到过类似的场景,给你两个实用的解决方案,完全不需要手动列出数百个列名:
方法一:纯PySpark原生实现(推荐)
这种方法不用把数据拉到Driver节点,适合任何数据量,而且是Spark原生操作,效率更高。核心是用Spark 2.4+支持的stack函数,我们可以动态生成对应的表达式来适配所有列:
# 获取DataFrame的所有列名 all_columns = df.columns # 动态生成stack表达式:stack(列数, '列名1', 列名1, '列名2', 列名2, ...) # repr(c)会把列名转成字符串常量,避免列名含特殊字符时出错 stack_expression = f"stack({len(all_columns)}, {', '.join([f'{repr(c)}, {c}' for c in all_columns])}) as (Name, Views)" # 执行转换,原DataFrame只有一行,直接select即可 result_df = df.selectExpr(stack_expression)
执行后result_df就是你想要的两列结构,Name是原列名,Views是对应的值。
方法二:借助Pandas转换(适合小数据量)
如果你的数据量很小(比如只有一行数百列),用Pandas转置的方式也可以,不过需要优化一下原代码的步骤,让结果更贴合需求:
# 把PySpark DataFrame转成Pandas DataFrame pd_df = df.toPandas() # 转置后重置索引,并重命名列 result_pd = pd_df.transpose().reset_index().rename(columns={'index': 'Name', 0: 'Views'}) # 如果需要转回PySpark DataFrame result_df = spark.createDataFrame(result_pd)
两种方法的对比
- 方法一:纯Spark原生,不依赖Pandas,不会把数据拉到Driver节点,适合大数据场景,稳定性更好。
- 方法二:代码更直观,但
toPandas()会把数据加载到Driver内存,只适合小数据量的情况。
另外要注意:如果你的Spark版本低于2.4,stack函数不支持,那可以考虑用explode结合create_map的方式,不过Databricks的Runtime一般都满足2.4+的要求,所以第一种方法应该没问题。
内容的提问来源于stack exchange,提问作者Madno
相关产品推荐
相关产品推荐

