【问题标题】:Unable to explode() Map[String, Struct] in Spark无法在 Spark 中爆炸() Map [String,Struct]
【发布时间】:2019-08-09 18:43:12
【问题描述】:

为此苦苦挣扎了一段时间,但我仍然无法解决这个问题。

我正在尝试 flatMap(或者使用 .withColumnexplode(),因为它看起来更容易,所以我不会丢失列名),但我总是收到错误 UDTF expected 2 aliases but got 'name' instead

我已经重新审视了一些类似的问题,但由于架构过于简单,因此没有一个能说明问题。

我尝试执行 flatMap 的架构列是以下...

StructField(CarMake,
  StructType(
    List(
      StructField(
        Models,
        MapType(
          StringType,
          StructType(
            List(
              StructField(Variant, StringType),
              StructField(GasOrPetrol, StringType)
            )
          )
        )
      )
    )
  ))

我想通过像这样调用explode()来实现...

carsDS
      .withColumn("modelsAndVariant", explode($"carmake.models"))

...是在没有嵌套的 Map 和 Struct 的情况下实现 Row,因此我得到的行数与变体一样多。

输入示例

(country: Sweden, carMake: Volvo, carMake.Models: {"850": ("T5", "petrol"), "V50": ("T5", "petrol")})

示例输出

(country: Sweden, carMake: Volvo, Model: "850", Variant: "T5", GasOrPetrol: "petrol"}
(country: Sweden, carMake: Volvo, Model: "V50", Variant: "T5", GasOrPetrol: "petrol"}

基本上将嵌套的 Map 及其内部 Struct 都留在同一级别。

【问题讨论】:

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


【解决方案1】:

试试这个:

case class Models(variant:String, gasOrPetrol:String)
case class CarMake(brand:String, models : Map[String, Models] )
case class MyRow(carMake:CarMake)

val df = List(
  MyRow(CarMake("volvo",Map(
    "850" -> Models("T5","petrol"),
    "V50" -> Models("T5","petrol")
  )))
).toDF()

df.printSchema()

df.show()

给予

root
 |-- carMake: struct (nullable = true)
 |    |-- brand: string (nullable = true)
 |    |-- models: map (nullable = true)
 |    |    |-- key: string
 |    |    |-- value: struct (valueContainsNull = true)
 |    |    |    |-- variant: string (nullable = true)
 |    |    |    |-- gasOrPetrol: string (nullable = true)


+--------------------+
|             carMake|
+--------------------+
|[volvo, [850 -> [...|
+--------------------+

现在爆炸,注意withColumn 不起作用,因为地图上的èxplode 返回2 列(keyvalue),所以你需要使用select

val cols: Array[Column] = df.columns.map(col)

df
  .select((cols:+explode($"carMake.models")):_*)
  .select((cols:+$"key".as("model"):+$"value.*"):_*)
  .show()

给予:

+--------------------+-----+-------+-----------+
|             carMake|model|variant|gasOrPetrol|
+--------------------+-----+-------+-----------+
|[volvo, [850 -> [...|  850|     T5|     petrol|
|[volvo, [850 -> [...|  V50|     T5|     petrol|
+--------------------+-----+-------+-----------+

【讨论】:

  • 非常感谢您的快速答复!很抱歉没有提供代码进行快速测试,我不得不匆忙离开,直到现在才回来,非常感谢:)
猜你喜欢
  • 2021-12-09
  • 2021-08-09
  • 2022-01-16
  • 2018-04-27
  • 2019-04-04
  • 1970-01-01
  • 2021-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多