Spark DataFrame转置时含点列名的解析问题求助
解决Spark DataFrame列名带点号的转置问题
问题原因
列名里的点号会被Spark误认为是嵌套字段的分隔符(比如ac.inc会被解析成ac结构体下的inc字段),直接用col(cname)会找不到对应列,导致原代码失效。
解决方案1:修改原map+explode代码,用反引号包裹列名
把列名用反引号(`)包裹,明确告诉Spark这是完整的列名,不是嵌套结构。修改后的代码如下:
import org.apache.spark.sql.functions.{lit, col, explode, map} df.select( map(df.columns.flatMap(cname => Seq(lit(cname), col(s"`$cname`"))):_*).as("map") ).select( explode($"map").alias("company", "value") ).show()
这里的s"$cname"会自动给每个带点号的列名加上反引号,让Spark正确识别列名。
解决方案2:用Spark原生的Unpivot操作(更高效简洁)
对于宽表转长表的场景,Spark的stack函数是专门做这个的,比map+explode更高效。可以手动或动态生成表达式:
手动写表达式(列少的情况)
import org.apache.spark.sql.functions.col val unpivotExpr = "stack(4, 'ac.inc', `ac.inc`, 'b.corp', `b.corp`, 'cdi.ltd', `cdi.ltd`, 'd.corp', `d.corp`) as (company, value)" df.selectExpr(unpivotExpr).show()
动态生成表达式(列多的情况)
如果列名很多,不需要手动逐个写,用代码自动生成:
val columns = df.columns val stackExpr = s"stack(${columns.length}, ${columns.flatMap(c => s"'$c', `$c`").mkString(", ")}) as (company, value)" df.selectExpr(stackExpr).show()
两种方法都能输出你想要的长表结构,解决列名带点号的解析问题。
内容的提问来源于stack exchange,提问作者Lokesh
相关产品推荐
相关产品推荐

