我正在学习Spark和Scala,并在Spark REPL中进行了实验。
当我尝试将列表转换为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?
答案 0 :(得分:4)
如果您正在寻求使每个序列的每个元素分别位于各列的每一行的方法,那么以下是为您提供的选项
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 |
+------+------+
另一种更好的方法是使用压缩为
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
像zip
和zipped
那样合并所有序列,但是返回列表而不是元组,因此需要一些修改,因为
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 |
+------+------+------+
以此类推...
注意:转置要求所有序列的长度都相同
我希望答案会有所帮助
答案 1 :(得分:0)
默认情况下,每个元素都被视为dataFrame的Row。 如果您希望每个Seqs是不同的列,则需要将它们分组到一个Tuple中:
val twoColumnDf =Seq((Seq(1,2,3,4,5), Seq(5,4,3,2,3))).toDF("Field1", "Field2")
twoColumnDf.show
+---------------+---------------+
| Field1| Field2|
+---------------+---------------+
|[1, 2, 3, 4, 5]|[5, 4, 3, 2, 3]|
+---------------+---------------+