使用Spark DataFrame转置表格

时间:2018-07-07 13:10:29

标签: apache-spark dataframe

下面是我的输入DataFrame

+------+-------+---+------+-----+-----+-----+-----+-----+-----+
|number|word   |ID |Name  |prd_1|prd_2|prd_3|prd_4|prd_5|prd_6|
+------+-------+---+------+-----+-----+-----+-----+-----+-----+
|1     |bat    |101|Naman |2    |3    |8    |4    |5    |10   |
|2     |abc    |102|Bhagat|3    |8    |7    |9    |8    |11   |
|3     |abcd   |103|Anchal|1    |9    |2    |3    |6    |12   |
|4     |abcde  |104|Dev   |8    |6    |9    |4    |5    |13   |
|3     |abcdef |105|PArul |2    |7    |8    |7    |3    |14   |
|1     |abcdefg|106|Vipul |3    |4    |2    |8    |4    |15   |
+------+-------+---+------+-----+-----+-----+-----+-----+-----+

现在我想将prd_1prd_2prd_3换成一个单独的列,例如col1prd_4prd_5,{{ 1}}至prd_6
以下是我正在寻找的预期输出col2

DataFrame

这是我尝试的:

number|word   |ID |Name  |col1|col2|
+------+-------+---+------+----+----+
|1     |bat    |101|Naman |2   |4   |
|1     |bat    |101|Naman |3   |5   |
|1     |bat    |101|Naman |8   |10  |
|2     |abc    |102|Bhagat|3   |9   |
|2     |abc    |102|Bhagat|8   |8   |
|2     |abc    |102|Bhagat|7   |11  |
|3     |abcd   |103|Anchal|1   |3   |
|3     |abcd   |103|Anchal|9   |6   |
|3     |abcd   |103|Anchal|2   |12  | 

爆炸功能仅在select语句中起作用一次,并且在连续的select语句中使用它会创建很多不必要的行,我想在单个select语句中使用爆炸7-8次。另外,我要合并到单个列中的列数将始终保持不变。

3 个答案:

答案 0 :(得分:0)

您可以简单地zip myArray1myArray2,然后使用压缩的columNames 创建structs并将结构收集为{{ 1}}和array数组列。最后,您可以使用explode表示法将struct列拆分为单独的列

.*

应将您期望的输出显示为

val zippedCols = myArray1.zip(myArray2)

val testDf = df2.withColumn("newCol", explode(array(zippedCols.map(cols => struct(col(cols._1).as("col1"), col(cols._2).as("col2"))):_*)))
  .select(col("number"), col("word"), col("ID"), col("Name"), col("newCol.*"))

我希望答案会有所帮助

答案 1 :(得分:0)

这是在df上使用flatMap的另一种解决方案

urls.py

答案 2 :(得分:0)

另一种实现方式

val src_df=spark.read.option("header","true").csv("src file")
val mapped_df = src_df.groupBy(col("number"),col("word"),col("ID"),col("Name")).agg(collect_list(map($"prd_1",$"prd_4")) as "map_1",collect_list(map($"prd_2",$"prd_5")) as "map_2",collect_list(map($"prd_3",$"prd_6")) as "map_3")
def mergeUdf = udf((map1: Seq[Map[String, String]], map2: Seq[Map[String, String]],map3: Seq[Map[String, String]])=> map1.toList.flatten.toMap ++ map2.toList.flatten.toMap ++ map3.toList.flatten.toMap)
val new_df= mapped_df.withColumn("merged", mergeUdf(col("map_1"), col("map_2"),col("map_3"))).drop("map_1", "map_2","map_3")
new_df.select(col("number"),col("word"),col("ID"),col("Name"),explode($"merged")).show(false)