You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用PySpark对DataFrame执行逆透视(Unpivot)转换?

PySpark宽表转长表(逆透视)正确实现

要实现宽格式DataFrame转长格式,PySpark里直接用stack函数就能搞定,不用绕弯路。以下是具体步骤和代码:

核心思路

逆透视的本质是把多列(指标列)“堆叠”成两列:一列存原列名(指标名称),一列存对应的值。stack函数就是干这个的,它需要指定要堆叠的列数,然后依次列出'列名', 列的配对。

代码实现

假设你的宽表df结构如下(以销售数据为例):

AnoVendasCustosLucro
20201000500500
20211200600600

方法1:动态适配列(推荐)

如果指标列数量不固定,用动态生成stack表达式的方式,避免硬编码:

from pyspark.sql.functions import expr

# 排除年份列"Ano",得到所有要逆透视的指标列
unpivot_columns = [col for col in df.columns if col != "Ano"]

# 构造stack表达式:stack(列数, '列名1', 列1, '列名2', 列2, ...)
stack_expression = f"stack({len(unpivot_columns)}, {', '.join([f'\'{col}\', {col}' for col in unpivot_columns])}) as (Metrica, Valor)"

# 执行逆透视,保留年份列,加上堆叠后的两列
long_format_df = df.select("Ano", expr(stack_expression))

方法2:硬编码列(适合列固定的场景)

如果指标列是固定的,直接写死stack参数更直观:

from pyspark.sql.functions import expr

long_format_df = df.select(
    "Ano",
    expr("stack(3, 'Vendas', Vendas, 'Custos', Custos, 'Lucro', Lucro) as (Metrica, Valor)")
)

结果验证

运行后得到的长表就是你要的格式:

AnoMetricaValor
2020Vendas1000
2020Custos500
2020Lucro500
2021Vendas1200
2021Custos600
2021Lucro600

常见问题排查

如果你的代码输出不对,大概率是这几个原因:

  • stack函数第一个参数(要堆叠的列数)和实际列数不匹配,比如你有3个指标列,却写了2;
  • 列名配对写错,比如把'Vendas', Vendas写成了Vendas, 'Vendas',顺序反了;
  • 没有保留Ano列,导致年份信息丢失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 10:50:37