искривление преобразования кадра данных в набор данных с использованием класса case с полями option - PullRequest
0 голосов
/ 12 марта 2019

У меня есть следующий класс дел:

case class Person(name: String, lastname: Option[String] = None, age: BigInt) {}

И следующий JSON:

{ "name": "bemjamin", "age" : 1 }

Когда я пытаюсь преобразовать мой фрейм данных в набор данных:

spark.read.json("example.json")
  .as[Person].show()

Это показывает мне следующую ошибку:

Исключение в потоке "main" org.apache.spark.sql.AnalysisException: не может разрешить 'lastname' для указанных столбцов ввода: [age, name];

Мой вопрос таков: если моя схема относится к классу дел и определяет, что фамилия является необязательной, не должно ли as () выполнять преобразование?

Я легко могу это исправить, используя .map, но мне хотелось бы знать, есть ли другая более чистая альтернатива этому.

Ответы [ 2 ]

3 голосов
/ 12 марта 2019

У нас есть еще один вариант решения вышеуказанной проблемы. Требуется 2 шага

  1. Убедитесь, что поля, которые могут отсутствовать, объявляются как типы Scala, допускающие обнуление (например, Option [_]).

  2. Предоставить аргумент схемы и не зависеть от вывода схемы. Например, вы можете использовать Spark SQL Encoder :

    import org.apache.spark.sql.Encoders
    
    val schema = Encoders.product[Person].schema
    

Вы можете обновить код, как показано ниже.

val schema = Encoders.product[Person].schema

val df = spark.read
           .schema(schema)
           .json("/Users/../Desktop/example.json")
           .as[Person]

+--------+--------+---+
|    name|lastname|age|
+--------+--------+---+
|bemjamin|    null|  1|
+--------+--------+---+
1 голос
/ 12 марта 2019

Когда вы выполняете spark.read.json("example.json").as[Person].show(), он в основном считывает фрейм данных как

FileScan json [age#6L,name#7]

, а затем пытается применить объект Encoders for Person, следовательно, получает исключение AnalysisEx, поскольку он не может найти lastname из вашего файла json.

Либо вы можете намекнуть, что фамилия необязательна, указав некоторые данные с фамилией, либо попробовать это:

val schema: StructType = ScalaReflection.schemaFor[Person].dataType.asInstanceOf[StructType]
val x = spark.read
      .schema(schema)
      .json("src/main/resources/json/x.json")
      .as[Person]
+--------+--------+---+
|    name|lastname|age|
+--------+--------+---+
|bemjamin|    null|  1|
+--------+--------+---+

Надеюсь, это поможет.

...