【问题标题】:How to create Dataset (not DataFrame) without using case class but using StructType?如何在不使用案例类但使用 StructType 的情况下创建数据集(不是 DataFrame)?
【发布时间】:2021-01-27 23:29:23
【问题描述】:

如何使用StructType 创建数据集?

我们可以如下创建Dataset

case class Person(name: String, age: Int)

val personDS = Seq(Person("Max", 33), Person("Adam", 32), Person("Muller", 
62)).toDS()
personDS.show()

有没有办法在不使用案例类的情况下创建Dataset

我想使用案例类和StructType 创建一个DataFrame

【问题讨论】:

  • 您是否在考虑 DataFrame?它是 spark2 中 Dataset[Row] 的别名,可以使用 StructType 创建指定架构
  • DataFrame = Dataset[Row],所以如果你知道如何创建DataFrame,你就知道如何创建数据集:)
  • @T.Gaweda ,如果您看到此方法“spark.createDataset”,则没有选项可以传递“StructType”,如果您尝试使用 DataFrame 创建数据集,您仍然需要案例类

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


【解决方案1】:

如果您知道如何创建 DataFrame,那么您现在已经知道如何创建 Dataset :)

DataFrame = Dataset[Row].

这是什么意思?试试:

val df : DataFrame = spark.createDataFrame(...) // with StructType
import org.apache.spark.sql._
val ds : Dataset[Row] = df; // no error, as DataFrame is only a type alias of Dataset[Row]

【讨论】:

    【解决方案2】:

    从某种意义上说,这是一个有趣的问题,我看不出有人想要它的理由。

    如何使用“StructType”创建数据集

    然后我会问一个非常相似的问题...

    您为什么想用StructType“交易”一个案例类?这会给你什么是案例类所不能提供的?

    您使用案例类的原因是它可以同时为您提供两件事:

    1. 快速、准确且类型安全地描述您的架构

    2. 处理数据变得类型安全

    关于 1. 作为 Scala 开发人员,您将定义描述数据的业务对象。无论如何,您都必须这样做(除非您喜欢元组和_1 等)。

    关于类型安全(在 1. 和 2. 中)是关于转换数据以利用 Scala 编译器,该编译器可以帮助找到您期望 String 但具有 Int 的位置。对于StructType,检查仅在运行时(而非编译时)进行。

    综上所述,您的问题的答案是“是”。

    您可以使用StructType 创建数据集。

    scala> val personDS = Seq(("Max", 33), ("Adam", 32), ("Muller", 62)).toDS
    personDS: org.apache.spark.sql.Dataset[(String, Int)] = [_1: string, _2: int]
    
    scala> personDS.show
    +------+---+
    |    _1| _2|
    +------+---+
    |   Max| 33|
    |  Adam| 32|
    |Muller| 62|
    +------+---+
    

    您可能想知道为什么我看不到列名。这正是案例类的原因,它不仅可以为您提供类型,还可以为您提供列的名称。

    如果您不喜欢案例类,您可以使用一种技巧来避免处理它们。

    val withNames = personDS.toDF("name", "age").as[(String, Int)]
    scala> withNames.show
    +------+---+
    |  name|age|
    +------+---+
    |   Max| 33|
    |  Adam| 32|
    |Muller| 62|
    +------+---+
    

    【讨论】:

    • 我同意@jacek-laskowski 和你的观点,案例类比 StructType 有好处,但我提出这个问题的动机是,我正在为任何数据创建 DataFrame,只是为 conf 中的数据定义模式,我是动态构建 StructType,基于 conf 模式,如果可以通过数据集实现,我也在想同样的方法
    【解决方案3】:

    以下是使用 StructType 创建数据集的方法:

    import org.apache.spark.sql.types._
    import org.apache.spark.sql.Row
    
    val schema = StructType(Seq(
      StructField("name", StringType, true),
      StructField("age", IntegerType, true)
    ))
    
    val data = Seq(
      Row("Max", 33),
      Row("Adam", 32),
      Row("Muller", 62)
    )
    
    val personDF = spark.createDataFrame(
      spark.sparkContext.parallelize(data),
      schema
    )
    
    val yourDS = personDF.as[(String, Int)]
    
    yourDS.show()
    
    +------+---+
    |  name|age|
    +------+---+
    |   Max| 33|
    |  Adam| 32|
    |Muller| 62|
    +------+---+
    

    yourDSorg.apache.spark.sql.Dataset[(String, Int)]

    您问题中的personDSorg.apache.spark.sql.Dataset[Person] 类型,所以这不会给出相同的结果。

    有关如何创建数据集的更多信息,请参阅this post

    【讨论】:

      猜你喜欢
      • 2017-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-05
      • 2017-01-05
      相关资源
      最近更新 更多