【问题标题】:How to cast an array of struct in a spark dataframe using selectExpr?如何使用 selectExpr 在 spark 数据框中转换结构数组?
【发布时间】:2019-01-08 06:13:29
【问题描述】:

如何在 spark 数据帧中转换结构数组?

让我通过一个例子来解释我想要做什么。 我们将首先创建一个包含行数组和嵌套行的数据框。我的整数尚未在数据框中转换,它们被创建为字符串:

import org.apache.spark.sql._
import org.apache.spark.sql.types._
val rows1 = Seq(
  Row("1", Row("a", "b"), "8.00", Seq(Row("1","2"), Row("12","22"))),
  Row("2", Row("c", "d"), "9.00", Seq(Row("3","4"), Row("33","44")))
)

val rows1Rdd = spark.sparkContext.parallelize(rows1, 4)

val schema1 = StructType(
  Seq(
    StructField("id", StringType, true),
    StructField("s1", StructType(
      Seq(
        StructField("x", StringType, true),
        StructField("y", StringType, true)
      )
    ), true),
    StructField("d", StringType, true),
    StructField("s2", ArrayType(StructType(
      Seq(
        StructField("u", StringType, true),
        StructField("v", StringType, true)
      )
    )), true)
  )
)

val df1 = spark.createDataFrame(rows1Rdd, schema1)

这是创建的数据框的架构:

       df1.printSchema
       root
       |-- id: string (nullable = true)
       |-- s1: struct (nullable = true)
       |    |-- x: string (nullable = true)
       |    |-- y: string (nullable = true)
       |-- d: string (nullable = true)
       |-- s2: array (nullable = true)
       |    |-- element: struct (containsNull = true)
       |    |    |-- u: string (nullable = true)
       |    |    |-- v: string (nullable = true)

我想要做的是将所有可以是整数的字符串转换为整数。我尝试执行以下操作,但没有成功:

df1.selectExpr("CAST (id AS INTEGER) as id",
  "STRUCT (s1.x, s1.y) AS s1",
  "CAST (d AS DECIMAL) as d",
  "Array (Struct(CAST (s2.u AS INTEGER), CAST (s2.v AS INTEGER))) as s2").show()

我遇到了以下异常:

cannot resolve 'CAST(`s2`.`u` AS INT)' due to data type mismatch: cannot cast array<string> to int; line 1 pos 14;

任何人都有正确的查询将所有值转换为 INTEGER 吗?我将不胜感激。

非常感谢,

【问题讨论】:

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


    【解决方案1】:

    你应该匹配一个完整的结构:

    val result = df1.selectExpr(
      "CAST(id AS integer) id",
      "s1",
      "CAST(d AS decimal) d",
      "CAST(s2 AS array<struct<u:integer,v:integer>>) s2"
    )
    

    这应该给你以下架构:

    result.printSchema
    
    root
     |-- id: integer (nullable = true)
     |-- s1: struct (nullable = true)
     |    |-- x: string (nullable = true)
     |    |-- y: string (nullable = true)
     |-- d: decimal(10,0) (nullable = true)
     |-- s2: array (nullable = true)
     |    |-- element: struct (containsNull = true)
     |    |    |-- u: integer (nullable = true)
     |    |    |-- v: integer (nullable = true)
    

    和数据:

    result.show
    
    +---+-----+---+----------------+
    | id|   s1|  d|              s2|
    +---+-----+---+----------------+
    |  1|[a,b]|  8|[[1,2], [12,22]]|
    |  2|[c,d]|  9|[[3,4], [33,44]]|
    +---+-----+---+----------------+
    

    【讨论】:

    • 对于那些寻找如何直接使用数据帧来执行此操作的人,您只需使用与 selectExpr 相同的方式转换数组。例如。 result1 = df1.withColumn("s2", F.col("s2").cast("array>"))
    • 如果我只需要将 u 转换为整数而不需要包含 v 怎么办?
    猜你喜欢
    • 2022-08-04
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 2017-06-05
    • 1970-01-01
    • 2018-08-01
    • 2018-01-12
    • 2021-08-13
    相关资源
    最近更新 更多