Как преобразовать DataFrame в набор данных в Apache Spark на Java?

Я могу очень легко преобразовать DataFrame в набор данных в Scala:

case class Person(name:String, age:Long)
val df = ctx.read.json("/tmp/persons.json")
val ds = df.as[Person]
ds.printSchema

но в версии Java я не знаю, как преобразовать Dataframe в набор данных? Есть идеи?

мои усилия:

DataFrame df = ctx.read().json(logFile);
Encoder<Person> encoder = new Encoder<>();
Dataset<Person> ds = new Dataset<Person>(ctx,df.logicalPlan(),encoder);
ds.printSchema();

но компилятор говорит:

Error:(23, 27) java: org.apache.spark.sql.Encoder is abstract; cannot be instantiated

Отредактировано (решение):

решение, основанное на ответах @Leet-Falcon:

DataFrame df = ctx.read().json(logFile);
Encoder<Person> encoder = Encoders.bean(Person.class);
Dataset<Person> ds = new Dataset<Person>(ctx, df.logicalPlan(), encoder);

person Milad Khajavi    schedule 07.01.2016    source источник
comment
Похоже, API отсутствует для Java/w Spark 1.6.   -  person Leet-Falcon    schedule 07.01.2016
comment
как я могу написать недостающий API в Java?   -  person Milad Khajavi    schedule 07.01.2016


Ответы (2)


Официальные документы Spark предлагаются в API набора данных следующее:

Кодировщики Java указываются путем вызова статических методов в Кодировщики.

List<String> data = Arrays.asList("abc", "abc", "xyz");
Dataset<String> ds = context.createDataset(data, Encoders.STRING());

Кодировщики могут быть составлены в кортежи:

Encoder<Tuple2<Integer, String>> encoder2 = Encoders.tuple(Encoders.INT(), Encoders.STRING());
List<Tuple2<Integer, String>> data2 = Arrays.asList(new scala.Tuple2(1, "a");
Dataset<Tuple2<Integer, String>> ds2 = context.createDataset(data2, encoder2);

Или создан из Java Beans с помощью Кодировщики#bean:

Encoders.bean(MyClass.class);
person Leet-Falcon    schedule 07.01.2016
comment
Есть ли влияние на производительность при преобразовании DataFrame в набор данных? В частности, что происходит, когда я присоединяю кодировщик к кадру данных? Является ли кодировщик «ленивым» (т.е. он ничего не делает, если не вызывается типизированная операция) или он должен сначала обрабатывать DataFrame? - person Marsellus Wallace; 27.04.2017

Если вы хотите преобразовать общий DF в набор данных на Java, вы можете использовать класс RowEncoder, как показано ниже.

DataFrame df = sql.read().json(sc.parallelize(ImmutableList.of(
            "{\"id\": 0, \"phoneNumber\": 109, \"zip\": \"94102\"}"
    )));

    Dataset<Row> dataset = df.as(RowEncoder$.MODULE$.apply(df.schema()));
person nomad    schedule 27.10.2016
comment
Вот так в scala val encoder = Encoders.product[Foo] df.as[Foo](encoder) - person Painy James; 11.04.2017
comment
Проблема в том, что класс DataFrame ушел из Spark 2! - person Thomas Decaux; 01.03.2018
comment
Он не работает как есть. Набор данных‹Строка› набор данных = df.as(RowEncoder$.MODULE$.apply(df.schema())); получение ошибки несовместимого типа. - person Vamshavardhan Reddy; 12.04.2018