Dataframe в набор данных, который имеет тип Any

Недавно я перешел со Spark 1.6 на Spark 2.X и хотел бы также перейти, где это возможно, с фреймов данных на наборы данных. Я пробовал такой код

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. Итак, как я могу использовать наборы данных?


person navige    schedule 06.01.2017    source источник


Ответы (1)


Если вас не интересуют ограниченные и уродливые обходные пути, такие как 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])

or

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 и сопряжен со значительным снижением производительности и объема памяти.

Если для данного выполнения все значения одного типа, вы, конечно, можете создать специализированные классы и принять решение, какой из них использовать во время выполнения.

person zero323    schedule 06.01.2017