【问题标题】:Encoder[Row] in Scala SparkScala Spark 中的编码器[Row]
【发布时间】:2017-02-09 10:36:30
【问题描述】:

我正在尝试在 Spark 2.0.0 中对 Dataset[Row] (DataFrame) 执行简单映射。就这么简单

val df: DataSet[Row] = ...
df.map { r: Row => r }

但是编译器抱怨我没有向 map 函数提供隐式 Encoder[Row] 参数:

方法映射的参数不足:(隐含证据$7: 编码器[行])。

如果我首先转换为 RDD ds.rdd.map { r: Row => r },一切正常,但不应该有一种简单的方法来获得 Encoder[Row],就像元组类型 Encoders.product[(Int, Double)] 一样?

[请注意,我的Row 是动态调整大小的,因此无法轻易转换为强类型的Dataset。]

【问题讨论】:

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


    【解决方案1】:

    Encoder 需要知道如何将元素打包到 Row 中。因此,您可以使用row.structType 编写自己的Encoder[Row],该row.structType 在运行时确定Row 的元素并使用相应的解码器。

    或者,如果您对进入 Row 的数据有更多了解,您可以使用 https://github.com/adelbertc/frameless/

    【讨论】:

      【解决方案2】:

      Sry 迟到“有点”。希望这对现在遇到问题的人有所帮助。定义编码器的最简单方法是从现有 DataFrame 中派生结构:

      val df = Seq((1, "a"), (2, "b"), (3, "c").toDF("id", "name")
      val myEncoder = RowEndocer(df.schema)
      

      当您需要更改原始 DataFrame 中的现有字段时,这种方法可能很有用。

      如果您正在处理全新的结构,则依赖于 StructTypeStructField 的显式定义(如 @Reactormonk 的小神秘回复中所建议的那样)。

      定义相同编码器的示例:

      val myEncoder2 = RowEncoder(StructType(
        Seq(StructField("id", IntegerType), 
            StructField("name", StringType)
        )))
      

      请记住org.apache.spark.sql._org.apache.spark.sql.types._org.apache.spark.sql.catalyst.encoders.RowEncoder 库必须被导入。

      【讨论】:

      • 您可以简单地使用df.encoder,而不是RowEncoder(df.schema)
      【解决方案3】:

      在映射函数不更改架构的特定情况下,您可以传入 DataFrame 本身的编码器:

      df.map(r => r)(df.encoder)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-21
        • 1970-01-01
        • 1970-01-01
        • 2016-06-20
        • 2021-03-08
        • 2018-08-23
        • 2022-09-27
        相关资源
        最近更新 更多