将类型为Any的Dataframe转换为Dataset

4

我最近从Spark 1.6升级到了Spark 2.X,希望尽可能地从DataFrames转移到Datasets。我尝试了以下代码:

case class MyClass(a : Any, ...)

val df = ...
df.map(x => MyClass(x.get(0), ...))

正如你所看到的,MyClass 有一个类型为 Any 的字段。因为我在编译时不知道通过 x.get(0) 检索的字段的类型。它可能是长整型、字符串、整型等。

然而,当我尝试执行类似上面所示的代码时,会出现异常:

java.lang.ClassNotFoundException: scala.Any

通过一些调试,我意识到异常的产生并不是因为我的数据类型是Any,而是因为MyClass的类型是Any。那么我该如何使用数据集呢?

1个回答

4

除非您对像Encoders.kryo这样的有限和丑陋的解决方案感兴趣:

import org.apache.spark.sql.Encoders

case class FooBar(foo: Int, bar: Any)

spark.createDataset(
  sc.parallelize(Seq(FooBar(1, "a")))
)(Encoders.kryo[FooBar])

或者
spark.createDataset(
  sc.parallelize(Seq(FooBar(1, "a"))).map(x => (x.foo, x.bar))
)(Encoders.tuple(Encoders.scalaInt, Encoders.kryo[Any]))

您不能这样做。 Dataset 中的所有字段/列必须是已知的、同质的类型,该类型在作用域中有隐式的 Encoder。那里根本没有 Any 的位置。

UDT API 提供了一些灵活性,并允许有限的多态性,但它是私有的,与 Dataset API 不完全兼容,并带有显著的性能和存储成本。

如果对于给定的执行,所有值都是相同类型的,当然可以创建专门的类并在运行时做出使用哪个类的决策。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接