【问题标题】:How to convert a List of Lists to a DataFrame in Scala?如何将列表列表转换为 Scala 中的 DataFrame?
【发布时间】:2018-06-22 07:22:46
【问题描述】:

我正在学习 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 中将这样的 List 列表转换为 DataFrame?

【问题讨论】:

    标签: scala apache-spark


    【解决方案1】:

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

    压缩

    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 指出这一点

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

    转置

    Tansposezipzipped 一样组合所有序列,但返回列表而不是元组,因此需要一点黑客攻击

    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    |
    +------+------+------+
    

    等等……

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

    希望回答对你有帮助

    【讨论】:

    • 如果我想要 3 个 Seqs 和 3 个 Columns 怎么办? eq(1,2,3,4,5).zip(Seq(5,4,3,2,3)).zip(Seq(10,10,10,12,14)).toDF("Field1", "Field2", "Field3") 给出一个例外。
    • @user3243499:或者您可以直接将其写为元组序列:Seq((1,5,10), (2,4,10), (3,3,10), (4,2,12), (5,3,14)).toDF("Field1", "Field2", "Field3"),这在某些情况下会更容易。
    • @Shaido 感谢您的指出。我猜转置是正确的解决方案:)
    • @RameshMaharjan:是的,那个看起来更有用。 :)
    【解决方案2】:

    默认情况下,每个元素都被认为是 dataFrame 的一个 Row。 如果您希望每个 Seq 成为不同的列,则需要将它们分组到一个元组中:

    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]|
    +---------------+---------------+
    

    【讨论】:

      猜你喜欢
      • 2019-02-24
      • 2013-02-13
      • 2015-02-20
      • 1970-01-01
      • 2022-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-16
      相关资源
      最近更新 更多