如何在不使用case类但使用StructType的情况下创建数据集(而不是DataFrame)?

时间:2017-09-18 17:43:23

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

如何使用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

我想使用案例类并使用DataFrame创建StructType

3 个答案:

答案 0 :(得分:4)

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

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]

答案 1 :(得分:1)

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

  

如何使用“StructType”

创建数据集
然后,我会问一个非常相似的问题...

  

为什么要用StructType“交易”案例类?那个案例类不能给你什么呢?

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

  1. 快速,完美且类型安全地描述您的架构

  2. 使用您的数据会变得类型安全

  3. 关于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|
    +------+---+
    

答案 2 :(得分:0)

以下是使用 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|
+------+---+

yourDS 是一个 org.apache.spark.sql.Dataset[(String, Int)]

您问题中的 personDS 属于 org.apache.spark.sql.Dataset[Person] 类型,因此这不会给出完全相同的结果。

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