Scala Spark中的编码器[Row]

时间:2016-09-30 19:04:49

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

我正在尝试在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。]

2 个答案:

答案 0 :(得分:1)

0,1=> as above 2=> 0+2*2 1+2*2 3=> 0+2*3 1+2*3 1+2*2 0+2*2 1+2*3 0+2*3 需要知道如何将元素打包到// i: row, j: column, n: matrix dimension var v = 0; var m = 2; do { var p = m/2; v = v*2 + (i%(n/p) < n/m == j%(n/p) < n/m ? 0 : 1); m *= 2; } while (m <= n); 中。因此,您可以使用Encoder编写自己的RowEncoder[Row]在运行时确定row.structType的元素并使用相应的解码器。

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

答案 1 :(得分:0)

很晚才成为“位”。希望这对现在遇到问题的人有所帮助。定义编码器的最简单方法是从现有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库。