【问题标题】:Spark scala create multiple columns from array columnSpark scala从数组列创建多个列
【发布时间】:2019-09-30 21:23:54
【问题描述】:

从数组列创建多个列

数据框

Car name |  details
Toyota   | [[year,2000],[price,20000]]
Audi     | [[mpg,22]]

预期数据帧

Car name | year | price | mpg
Toyota   | 2000 | 20000 | null
Audi     | null | null | 22

【问题讨论】:

  • 是 (year, 2000) 类型的 tuple 还是 map ?你能打印数据框的架构吗?
  • 由于您的问题与火花流无关,因此我放弃了。

标签: scala apache-spark apache-spark-sql


【解决方案1】:

你可以试试这个

让我们定义数据

scala> val carsDF = Seq(("toyota",Array(("year", 2000), ("price", 100000))), ("Audi", Array(("mpg", 22)))).toDF("car", "details")
carsDF: org.apache.spark.sql.DataFrame = [car: string, details: array<struct<_1:string,_2:int>>]

scala> carsDF.show(false)
+------+-----------------------------+
|car   |details                      |
+------+-----------------------------+
|toyota|[[year,2000], [price,100000]]|
|Audi  |[[mpg,22]]                   |
+------+-----------------------------+

拆分数据并访问数据中的值

scala> carsDF.withColumn("split", explode($"details")).withColumn("col", $"split"("_1")).withColumn("val", $"split"("_2")).select("car", "col", "val").show
+------+-----+------+
|   car|  col|   val|
+------+-----+------+
|toyota| year|  2000|
|toyota|price|100000|
|  Audi|  mpg|    22|
+------+-----+------+

定义所需列的列表

scala> val colNames = Seq("mpg", "price", "year", "dummy")
colNames: Seq[String] = List(mpg, price, year, dummy)

对上面定义的列名使用旋转可以得到所需的输出。 通过在序列中赋予新的列名使其成为单点输入

scala> weDF.groupBy("car").pivot("col", colNames).agg(avg($"val")).show
+------+----+--------+------+-----+
|   car| mpg|   price|  year|dummy|
+------+----+--------+------+-----+
|toyota|null|100000.0|2000.0| null|
|  Audi|22.0|    null|  null| null|
+------+----+--------+------+-----+

这似乎更优雅和简单的方式来实现输出

【讨论】:

    【解决方案2】:

    你可以这样做

    import org.apache.spark.functions.col
    val df: DataFrame = Seq(
      ("toyota",Array(("year", 2000), ("price", 100000))),
      ("toyota",Array(("year", 2001)))
    ).toDF("car", "details")
    
     +------+-------------------------------+
     |car   |details                        |
     +------+-------------------------------+
     |toyota|[[year, 2000], [price, 100000]]|
     |toyota|[[year, 2001]]                 |
     +------+-------------------------------+
    
    val newdf = df
      .withColumn("year", when(col("details")(0)("_1") === lit("year"), col("details")(0)("_2")).otherwise(col("details")(1)("_2")))
      .withColumn("price", when(col("details")(0)("_1") === lit("price"), col("details")(0)("_2")).otherwise(col("details")(1)("_2")))
      .drop("details")
    
    newdf.show()
      +------+----+------+
      |   car|year| price|
      +------+----+------+
      |toyota|2000|100000|     
      |toyota|2001|  null|
      +------+----+------+
    

    【讨论】:

    • 如果年份和价格元素不按顺序怎么办。
    • 您可以在 withColumn 中添加一个 when else 测试以查看值是年份还是价格
    • 嗨@firsni,我怎样才能让它动态我更新了问题。
    • 你需要一个 Map 而不是一个数组来使它动态
    猜你喜欢
    • 2021-11-20
    • 1970-01-01
    • 2020-09-22
    • 2020-08-04
    • 2019-04-04
    • 2021-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多