簡體   English   中英

使用定義的StructType轉換Spark數據幀的值

[英]Cast values of a Spark dataframe using a defined StructType

有沒有一種方法可以使用StructType轉換數據幀的所有值?

讓我用一個例子解釋我的問題:

假設我們從文件讀取后獲得了一個數據框(我提供了生成該數據框的代碼,但是在我的真實世界項目中,我從文件讀取后獲得了該數據框):

    import org.apache.spark.sql.{Row, SparkSession}
    import org.apache.spark.sql.types._
    import org.apache.spark.sql.functions._
    import spark.implicits._
    val rows1 = Seq(
      Row("1", Row("a", "b"), "8.00", Row("1","2")),
      Row("2", Row("c", "d"), "9.00", Row("3","4"))
    )

    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", StructType(
          Seq(
            StructField("u", StringType, true),
            StructField("v", StringType, true)
          )
        ), true)
      )
    )

    val df1 = spark.createDataFrame(rows1Rdd, schema1)

    println("Schema with nested struct")
    df1.printSchema()

    root
    |-- id: string (nullable = true)
    |-- s1: struct (nullable = true)
    |    |-- x: string (nullable = true)
    |    |-- y: string (nullable = true)
    |-- d: string (nullable = true)
    |-- s2: struct (nullable = true)
    |    |-- u: string (nullable = true)
    |    |-- v: string (nullable = true)

現在,假設我的客戶端為我提供了他想要的數據的架構(與讀取的數據框的架構等效,但是具有不同的數據類型(包含StringTypes,IntegerTypes ...)):

    val wantedSchema = StructType(
      Seq(
        StructField("id", IntegerType, true),
        StructField("s1", StructType(
          Seq(
            StructField("x", StringType, true),
            StructField("y", StringType, true)
          )
        ), true),
        StructField("d", DoubleType, true),
        StructField("s2", StructType(
          Seq(
            StructField("u", IntegerType, true),
            StructField("v", IntegerType, true)
          )
        ), true)
      )
    )

使用提供的StructType轉換數據框的值的最佳方法是什么?

如果有一種方法可以應用到數據幀上,那就很不錯了,它可以通過強制轉換所有值來應用新的StructType。

PS:這是一個小的數據框,僅作為示例,在我的項目中,該數據框包含更多行。 如果這是一個只有幾列的小型Dataframe,我可以很容易地進行轉換,但就我而言,我正在尋找一種智能的解決方案,可以通過應用StructType來轉換所有值,而不必手動轉換每個列/值。編碼。

我將很感激您能提供的任何幫助,非常感謝!

沒有自動執行轉換的方法。 您可以在Spark SQL中表達轉換邏輯,以便一次轉換所有內容-但是,如果您有很多字段,那么生成的SQL可能會變得很大。 但是至少您可以將所有轉換都放在一個地方。

例:

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

要注意的一件事是,每當轉換失敗時(例如,當d不是數字時),您將得到NULL 一種選擇是在轉換之前運行一些驗證,然后過濾掉df1記錄以僅轉換有效的記錄。

經過大量研究,這里有一個通用的解決方案,可以按照模式強制轉換數據框:

val castedDf = df1.selectExpr(wantedSchema.map(
  field => s"CAST ( ${field.name} As ${field.dataType.sql}) ${field.name}"
): _*)

這是強制轉換的數據框的架構:

castedDf.printSchema
root
|-- id: integer (nullable = true)
|-- s1: struct (nullable = true)
|    |-- x: string (nullable = true)
|    |-- y: string (nullable = true)
|-- d: double (nullable = true)
|-- s2: struct (nullable = true)
|    |-- u: integer (nullable = true)
|    |-- v: integer (nullable = true)

我希望它能對某人有所幫助,我花了5天的時間尋找這種簡單/通用的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM