Databricks中PySpark DataFrame奇数列逆透视错误,求正确方法
问题解答
stack方法是否仅适用于偶数个列?
不是。stack函数的第一个参数指定的是要逆透视的列的数量(即展开后生成的行数),后续每两个参数对应一组(列名标签、列值引用),只要总参数数量满足 1 + 2*N(N为待逆透视的列数)即可,和列数的奇偶性无关。
你的代码错误原因
你代码中的列名(如2015-04-01)包含-字符,直接写2015-04-01会被Spark解析为数学减法运算(2015-4-1),而非列名引用,这才导致错误结果。
正确的逆透视实现方式
方式1:修正原代码的列名引用
将所有列名用反引号(`)包裹,确保Spark正确识别为列名:
from pyspark.sql.functions import expr group = Inv_df.groupBy('Project', 'Project Description') # 修正列名引用,用反引号包裹带特殊字符的列名 unpivotExpr = "stack(69, '2015-04-01', `2015-04-01`, '2015-05-01', `2015-05-01`, '2015-06-01', `2015-06-01`, '2015-07-01', `2015-07-01`, '2015-08-01', `2015-08-01`, '2015-09-01', `2015-09-01`, '2015-10-01', `2015-10-01`, '2015-11-01', `2015-11-01`, '2015-12-01', `2015-12-01`, '2016-01-01', `2016-01-01`, '2016-02-01', `2016-02-01`, '2016-03-01', `2016-03-01`, '2016-04-01', `2016-04-01`, '2016-05-01', `2016-05-01`, '2016-06-01', `2016-06-01`, '2016-07-01', `2016-07-01`, '2016-08-01', `2016-08-01`, '2016-09-01', `2016-09-01`, '2016-10-01', `2016-10-01`, '2016-11-01', `2016-11-01`, '2016-12-01', `2016-12-01`, '2017-01-01', `2017-01-01`, '2017-02-01', `2017-02-01`, '2017-03-01', `2017-03-01`, '2017-04-01', `2017-04-01`, '2017-05-01', `2017-05-01`, '2017-06-01', `2017-06-01`, '2017-07-01', `2017-07-01`, '2017-08-01', `2017-08-01`, '2017-09-01', `2017-09-01`, '2017-10-01', `2017-10-01`, '2017-11-01', `2017-11-01`, '2017-12-01', `2017-12-01`, '2018-01-01', `2018-01-01`, '2018-02-01', `2018-02-01`, '2018-03-01', `2018-03-01`, '2018-04-01', `2018-04-01`, '2018-05-01', `2018-05-01`, '2018-06-01', `2018-06-01`, '2018-07-01', `2018-07-01`, '2018-08-01', `2018-08-01`, '2018-09-01', `2018-09-01`, '2018-10-01', `2018-10-01`, '2018-11-01', `2018-11-01`, '2018-12-01', `2018-12-01`, '2019-01-01', `2019-01-01`, '2019-02-01', `2019-02-01`, '2019-03-01', `2019-03-01`, '2019-04-01', `2019-04-01`, '2019-05-01', `2019-05-01`, '2019-06-01', `2019-06-01`, '2019-07-01', `2019-07-01`, '2019-08-01', `2019-08-01`, '2019-09-01', `2019-09-01`, '2019-10-01', `2019-10-01`, '2019-11-01', `2019-11-01`, '2019-12-01', `2019-12-01`, '2020-01-01', `2020-01-01`, '2020-02-01', `2020-02-01`, '2020-03-01', `2020-03-01`, '2020-04-01', `2020-04-01`, '2020-05-01', `2020-05-01`, '2020-06-01', `2020-06-01`, '2020-07-01', `2020-07-01`, '2020-08-01', `2020-08-01`, '2020-09-01', `2020-09-01`, '2020-10-01', `2020-10-01`, '2020-11-01', `2020-11-01`, '2020-12-01', `2020-12-01` ) as (Name, value)" unPivotDF = group.agg(expr(unpivotExpr))
方式2:动态生成stack表达式(更优雅,避免手动重复)
手动写69组参数容易出错,可通过代码自动生成表达式:
from pyspark.sql.functions import expr # 定义分组列 group_cols = ['Project', 'Project Description'] # 获取所有待逆透视的列(排除分组列) unpivot_cols = [col for col in Inv_df.columns if col not in group_cols] # 生成stack的参数部分:每列对应('列名', `列名`) stack_params = ", ".join([f"'{col}', `{col}`" for col in unpivot_cols]) # 拼接完整的stack表达式 unpivotExpr = f"stack({len(unpivot_cols)}, {stack_params}) as (Name, value)" # 执行逆透视 unPivotDF = Inv_df.groupBy(group_cols).agg(expr(unpivotExpr))
这种方式无需手动编写所有列,适配任意数量的待逆透视列,且自动处理带特殊字符的列名。
内容的提问来源于stack exchange,提问作者AzSurya Teja
相关产品推荐
相关产品推荐

