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

Spark中DataFrame列转置:Type与距离列组合生成新列

Spark Scala实现行转列并组合列名的方案

需求回顾

先明确下你的需求:把原始的多行多列数据(每个ID对应多个Type,每个Type有5m/10m/15m三个数值列),转换成以ID为主键,每个Type和距离列组合成新列(比如A_5m、B_10m)的宽表。

解决方案步骤

核心思路是先把多列的距离数据转成键值对(unpivot),再组合Type和距离生成目标列名,最后通过pivot转成宽表。

1. 准备示例数据

先模拟你的原始数据,方便后续测试:

import org.apache.spark.sql.functions._
import spark.implicits._

val df = spark.createDataFrame(Seq(
  (1, "A", 3, 9, 13),
  (1, "B", 7, 8, 22),
  (1, "C", 5, 11, 13),
  (2, "A", 1, 3, 20),
  (2, "B", 16, 17, 30)
)).toDF("ID", "Type", "5m", "10m", "15m")

2. Unpivot距离列(宽表转窄表)

用stack函数把5m、10m、15m这三个列转成两列:distance(存储列名,比如"5m")和value(存储对应数值):

val unpivotedDF = df.select(
  col("ID"),
  col("Type"),
  expr("stack(3, '5m', `5m`, '10m', `10m`, '15m', `15m`) as (distance, value)")
)

这里注意:因为列名以数字开头,需要用反引号`包裹,比如`5m`;stack(3, ...)里的3代表要转换的列数量。

3. 组合Type和distance生成目标列名

用concat函数把Type和distance拼接成新的列名格式(比如"A_5m"):

val combinedColDF = unpivotedDF.withColumn(
  "combined_col",
  concat(col("Type"), lit("_"), col("distance"))
)

4. Pivot转成目标宽表

以ID为分组键,对combined_col进行pivot操作,并用first函数聚合取对应的值(如果你的数据中每个ID+combined_col是唯一的,用first/max/min都可以):

val finalDF = combinedColDF.groupBy("ID")
  .pivot("combined_col")
  .agg(first("value"))

5. 查看结果

执行finalDF.show()就能得到你想要的格式:

+---+----+-----+-----+----+-----+-----+----+-----+-----+
| ID|A_5m|A_10m|A_15m|B_5m|B_10m|B_15m|C_5m|C_10m|C_15m|
+---+----+-----+-----+----+-----+-----+----+-----+-----+
|  1|   3|    9|   13|   7|    8|   22|   5|   11|   13|
|  2|   1|    3|   20|  16|   17|   30|null| null| null|
+---+----+-----+-----+----+-----+-----+----+-----+-----+

补充说明

  • 如果你的数据中存在同一个ID+Type+distance的重复记录,需要根据业务场景选择合适的聚合函数,比如sum(求和)、avg(平均值)等。
  • 如果需要指定列的顺序,可以在pivot时传入列名列表,比如.pivot("combined_col", Seq("A_5m", "A_10m", "A_15m", "B_5m", ...)),避免列顺序随机。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:44:55