首页 > 解决方案 > 如何将列表列表转换为 Scala 中的 DataFrame?

问题描述

我正在学习 Spark 和 Scala,并在 spark REPL 中进行试验。

当我尝试将 List 转换为 DataFrame 时,它​​的工作原理如下:

val convertedDf = Seq(1,2,3,4).toDF("Field1")

但是,当我尝试将列表列表转换为具有两列(field1、field2)的 DataFrame 时,它​​失败了

java.lang.IllegalArgumentException:要求失败:列数不匹配

错误信息:

val twoColumnDf =Seq(Seq(1,2,3,4,5), Seq(5,4,3,2,3)).toDF("Field1", (Field2))

如何将这样的列表列表转换为 Scala 中的 DataFrame?

标签: scalaapache-spark

解决方案


如果您正在寻找将每个序列的每个元素放在相应列的每一行中的方法,那么以下是适合您的选项

压缩

zip两个序列,然后应用toDF

val twoColumnDf =Seq(1,2,3,4,5).zip(Seq(5,4,3,2,3)).toDF("Field1", "Field2")

twoColumnDf这应该给你

+------+------+
|Field1|Field2|
+------+------+
|1     |5     |
|2     |4     |
|3     |3     |
|4     |2     |
|5     |3     |
+------+------+

拉链

另一种更好的方法是使用 zipped as

val threeColumnDf = (Seq(1,2,3,4,5), Seq(5,4,3,2,3), Seq(10,10,10,12,14)).zipped.toList.toDF("Field1", "Field2", "field3")

这应该给你

+------+------+------+
|Field1|Field2|field3|
+------+------+------+
|1     |5     |10    |
|2     |4     |10    |
|3     |3     |10    |
|4     |2     |12    |
|5     |3     |14    |
+------+------+------+

zipped仅适用于最多三个序列感谢您指出@Shaido

注意:行数由存在的最短序列决定

转置

Tanspose将所有序列按原样组合zipzipped但返回列表而不是元组,因此需要进行一些修改

Seq(Seq(1,2,3,4,5), Seq(5,4,3,2,3)).transpose.map{case List(a,b) => (a, b)}.toDF("Field1", "Field2")
+------+------+
|Field1|Field2|
+------+------+
|1     |5     |
|2     |4     |
|3     |3     |
|4     |2     |
|5     |3     |
+------+------+

Seq(Seq(1,2,3,4,5), Seq(5,4,3,2,3), Seq(10,10,10,12,14)).transpose.map{case List(a,b,c) => (a, b, c)}.toDF("Field1", "Field2", "Field3")
+------+------+------+
|Field1|Field2|Field3|
+------+------+------+
|1     |5     |10    |
|2     |4     |10    |
|3     |3     |10    |
|4     |2     |12    |
|5     |3     |14    |
+------+------+------+

等等 ...

注意:转置要求所有序列的长度相同

我希望答案有帮助


推荐阅读