类型为 Any 的数据框到数据集
Dataframe to Dataset which has type Any
我最近从 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
。那么我该如何使用数据集呢?
除非你对 感兴趣,比如 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 不完全兼容,并且会带来显着的性能和存储损失。
如果对于给定的执行所有相同类型的值,您当然可以创建专门的 类 并决定在 运行 时使用哪一个。
我最近从 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
。那么我该如何使用数据集呢?
除非你对 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 不完全兼容,并且会带来显着的性能和存储损失。
如果对于给定的执行所有相同类型的值,您当然可以创建专门的 类 并决定在 运行 时使用哪一个。