Как объединить вложенный json в Apache Spark

#apache-spark #pyspark

Вопрос:

Может ли кто-нибудь сообщить мне, где я ошибаюсь в своей попытке объединить вложенное поле JSON.

Я использую следующий код:

 df = (df  .withColumn("ingestion_date", current_timestamp())  .withColumn("name", concat(col("name.forename"),   lit(" "), col("name.surname"))))  )  

Схема:

 root  |-- driverRef: string (nullable = true)  |-- number: integer (nullable = true)  |-- code: string (nullable = true)  |-- forename: string (nullable = true)  |-- surname: string (nullable = true)  |-- dob: date (nullable = true)  

Как вы можете видеть, я пытаюсь объединить имя и фамилию, чтобы указать полное имя в поле имя. В настоящее время данные выглядят следующим образом:

введите описание изображения здесь

После объединения поля » имя «должно быть одно единственное значение, например, поле» имя «будет просто показывать Льюиса Гамильтона и, как и для других значений в поле «имя».

Мой код выдает следующую ошибку:

 Can't extract value from name#6976: need struct type but got string  

Комментарии:

1. Можете ли вы включить схему использования df.printSchema() фрейма данных ?

2. Полная схема выглядит следующим образом: root |-- driverRef: string (nullable = true) |-- number: integer (nullable = true) |-- code: string (nullable = true) |-- forename: string (nullable = true) |-- surname: string (nullable = true) |-- dob: date (nullable = true)

3. Извините, я не знаю, как отредактировать код, чтобы он выглядел аккуратнее

4. вы можете отредактировать вопрос, чтобы обновить его с помощью schama, очень важно правильно вложить его, так как от этого будут зависеть ответы.

5. В схеме, которую вы предоставили, я не вижу name столбца. Из-за ошибки я подозреваю, что name столбец является строкой, и вы не можете извлечь из него значения, как будто это карта. Обновите схему, чтобы иметь a MapType(StringType(), StringType()) , и вы сможете получить доступ к значениям.

Ответ №1:

Казалось бы , у вас есть фрейм данных, содержащий name столбец, содержащий json с двумя значениями: forename и surname , вот так {"forename": "Lewis", "surname" : "Hamilton"} .

Этот столбец в spark имеет строковый тип. Это объясняет полученную вами ошибку. Вы могли бы это сделать, только name.forename если name бы имели структуру типа с именем поля forename . Вот что значит «искра need struct type but got string «.

Вам просто нужно сказать spark, что этот строковый столбец является JSON и как его проанализировать.

 from pyspark.sql.types import StructType, StringType, StructField from pyspark.sql import functions as f  # initializing data df = spark.range(1).withColumn('name',  f.lit('{"forename": "Lewis", "surname" : "Hamilton"}')) df.show(truncate=False)  
  --- ---------------------------------------------  |id |name |  --- ---------------------------------------------  |0 |{"forename": "Lewis", "surname" : "Hamilton"}|  --- ---------------------------------------------   

И разбор этого JSON:

 json_schema = StructType([  StructField('forename', StringType()),  StructField('surname', StringType()) ])  df  .withColumn('s', f.from_json(f.col('name'), json_schema))  .withColumn("name", f.concat_ws(" ", f.col("s.forename"), f.col("s.surname")))  .show()  
  --- -------------- -----------------  | id| name| s|  --- -------------- -----------------  | 0|Lewis Hamilton|{Lewis, Hamilton}|  --- -------------- -----------------   

Вы можете чем — то избавиться s с drop помощью , он содержит проанализированные struct .