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

PySpark/Pandas实现宽表转长表:操作名称及方法问询

宽表转长表(Unpivot)的操作名称与实现

你要做的这个操作叫做 Unpivot(逆透视/宽表转长表),核心是将原本按列分组的类别数据(比如月份)转为行维度,把多列合并为「类别标识列」和「对应值列」。


PySpark 实现(优先推荐)

假设输入的宽表结构如下:

yearJanFebMar
2023100150200
2024120180220

方法1:使用 melt 函数(Spark 3.1+ 适用)

Spark 3.1 及以上版本内置了melt函数,能快速完成逆透视:

from pyspark.sql import functions as F
from pyspark.sql.types import StringType

# 假设df是你的输入DataFrame
melted_df = df.melt(
    id_vars=["year"],          # 保留的主键列
    value_vars=["Jan", "Feb", "Mar"],  # 需要转换的月份列
    var_name="month",          # 生成的月份标识列
    value_name="gain"          # 生成的数值列
)

# 转换为「年份_两位月份」格式
month_code_map = {"Jan": "01", "Feb": "02", "Mar": "03"}
get_month_code = F.udf(lambda m: month_code_map[m], StringType())

final_df = melted_df.withColumn(
    "year_month",
    F.concat(F.col("year").cast(StringType()), F.lit("_"), get_month_code(F.col("month")))
).drop("year", "month")

final_df.show()

方法2:使用 stack 表达式(兼容低版本Spark)

如果你的Spark版本低于3.1,用SQL的stack表达式手动实现:

# 构造stack表达式:stack(列数, '列名1', 列值1, '列名2', 列值2, ...)
stack_expr = "stack(3, 'Jan', Jan, 'Feb', Feb, 'Mar', Mar) as (month, gain)"

melted_df = df.selectExpr("year", stack_expr)

# 生成year_month列
final_df = melted_df.withColumn(
    "year_month",
    F.concat(
        F.col("year").cast(StringType()),
        F.lit("_"),
        F.when(F.col("month") == "Jan", "01")
         .when(F.col("month") == "Feb", "02")
         .when(F.col("month") == "Mar", "03")
    )
).drop("year", "month")

final_df.show()

Pandas 实现

先构造示例输入数据:

import pandas as pd

df = pd.DataFrame({
    "year": [2023, 2024],
    "Jan": [100, 120],
    "Feb": [150, 180],
    "Mar": [200, 220]
})

使用 melt 函数

Pandas的melt是处理这类转换的标准工具:

# 第一步:逆透视宽表
melted_df = df.melt(
    id_vars=["year"],
    value_vars=["Jan", "Feb", "Mar"],
    var_name="month",
    value_name="gain"
)

# 第二步:生成year_month列
month_code_map = {"Jan": "01", "Feb": "02", "Mar": "03"}
melted_df["year_month"] = melted_df["year"].astype(str) + "_" + melted_df["month"].map(month_code_map)

# 清理冗余列
final_df = melted_df.drop(["year", "month"], axis=1)
print(final_df)

内容的提问来源于stack exchange,提问作者vinicius de novaes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 07:53:33