#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
столбец является строкой, и вы не можете извлечь из него значения, как будто это карта. Обновите схему, чтобы иметь aMapType(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
.