如何将PySpark DataFrame列数据转成行数据并添加日期范围列?
PySpark实现需求的最优方案
你的需求核心是新增日期范围列+宽表转长表(列转行),最优方法是结合Spark原生的concat_ws(构造日期范围)和stack函数(列转行),无需额外依赖,性能高效。
步骤说明与代码示例
假设你的原始DataFrame结构如下(示例):
| start_date | end_date | 北京 | 上海 | 广州 |
|---|---|---|---|---|
| 2024-01-01 | 2024-01-07 | 100 | 200 | 150 |
1. 定义城市列列表
先把需要转行的城市列整理成列表(替换成你实际的列名):
city_cols = ["北京", "上海", "广州"]
2. 构造日期范围列 + 列转行
使用concat_ws拼接日期范围,再用stack将城市列转为行:
from pyspark.sql.functions import concat_ws # 构造stack表达式:stack(列数, 列名1, 列值1, 列名2, 列值2...) as (新列名1, 新列名2) stack_expr = f"stack({len(city_cols)}, {', '.join([f'{repr(col)}, {col}' for col in city_cols])}) as (城市, 数值)" # 执行转换 result_df = df.withColumn("日期范围", concat_ws(" - ", df.start_date, df.end_date)) \ .selectExpr("日期范围", stack_expr)
转换后的结果就会是:
| 日期范围 | 城市 | 数值 |
|---|---|---|
| 2024-01-01 - 2024-01-07 | 北京 | 100 |
| 2024-01-01 - 2024-01-07 | 上海 | 200 |
| 2024-01-01 - 2024-01-07 | 广州 | 150 |
关键优势
stack是Spark原生SQL函数,比自定义melt函数性能更优,尤其适合大数据量场景;- 代码简洁,无需引入第三方库,维护成本低;
- 日期范围的构造可灵活调整:如果你的原始数据是单日期(而非起止日期),可以用
date_trunc、date_add等函数生成范围,比如:from pyspark.sql.functions import date_trunc, date_add # 生成"本周"的日期范围 result_df = df.withColumn("日期范围", concat_ws(" - ", date_trunc("week", df.date), date_add(date_trunc("week", df.date), 6))) \ .selectExpr("日期范围", stack_expr)
内容的提问来源于stack exchange,提问作者Jie Zhang
相关产品推荐
相关产品推荐

