将列转置为Scala中的行

时间:2017-11-30 17:09:33

标签: scala pyspark apache-spark-sql pivot

需要转置数据框并使用Scala将其另存为外部表。 试图使用数据透视但没有运气,需要将DF中的所有列转换为行,并将相应的值转换为sample_value列。 我的DF

A B C D
1 2 3 4
1 2 3 4
2 3 4 1
2 3 4 1

需要最终输出为:

col_name  sample_value1 sample_value2
A         1             2
B         2             3
C         3             4
D         4             1

1 个答案:

答案 0 :(得分:0)

在我继续回答您的问题之前,我想强调的是,这是一个非常昂贵的解决方案,只有在您没有替代时才能使用。< / p>

dataframe视为

+---+---+---+---+
|A  |B  |C  |D  |
+---+---+---+---+
|1  |2  |3  |4  |
|1  |2  |3  |4  |
|2  |3  |4  |1  |
|2  |3  |4  |1  |
+---+---+---+---+

您可以执行以下操作,为最终new的headernames获取dataframe

import org.apache.spark.sql.functions.lit
import org.apache.spark.sql.functions.concat
import org.apache.spark.sql.functions.rank
import org.apache.spark.sql.expressions.Window
val tempdf = df.distinct().withColumn("new", concat(lit("sample_value"), rank.over(Window.partitionBy().orderBy("A")))).cache()

应该给你

+---+---+---+---+-------------+
|A  |B  |C  |D  |new          |
+---+---+---+---+-------------+
|1  |2  |3  |4  |sample_value1|
|2  |3  |4  |1  |sample_value2|
+---+---+---+---+-------------+

现在最后一个昂贵的部分是使用pivotunionwithColumngroupByaggregations来获得所需的输出

val firstCol = df.schema.fieldNames.head
val restOfCol = df.schema.fieldNames.tail
import org.apache.spark.sql.functions.first
var finaldf = tempdf.groupBy().pivot("new").agg(first(firstCol)).withColumn("col_name", lit(firstCol))

for(column <- restOfCol) {
  finaldf = finaldf.union(tempdf.groupBy().pivot("new").agg(first(column)).withColumn("col_name", lit(column)))
}

finaldf.show(false)

finaldf应该是

+-------------+-------------+--------+
|sample_value1|sample_value2|col_name|
+-------------+-------------+--------+
|1            |2            |A       |
|2            |3            |B       |
|3            |4            |C       |
|4            |1            |D       |
+-------------+-------------+--------+