数据框到数据集,类型为Any

时间:2017-01-06 11:43:04

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

我最近从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)检索的字段的类型。它可能是long,string,int等。

但是,当我尝试执行类似于上面所见的代码时,我得到一个例外:

java.lang.ClassNotFoundException: scala.Any

通过一些调试,我意识到引发了异常,不是因为我的数据类型为Any,而是因为MyClass的类型为Any。那么我怎样才能使用数据集呢?

1 个答案:

答案 0 :(得分:2)

除非您对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。那里Dataset没有地方。

UDT API提供了更多的灵活性并允许有限的多态性,但它是私有的,与next() API不完全兼容,并且具有显着的性能和存储损失。

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