Расчленить JSON ключевое значение для новых строк - PullRequest
2 голосов
/ 27 мая 2020

Я хочу преобразовать вложенный JSON и разбить его на новые строки.

Текущие данные:

+-----------+-----------+-----------------------------+
|         id|      site |                         sale|
+-----------------------------------------------------+
|        abc|          6|{"2019-05-08T00:00:00": null, "2019-05-09T00:00:00": [{"key1": 2, "key2": 0}]}         |
|        def|          5|{"2019-05-08T00:00:00": [{"key1": 22, "key2": 10}], "2019-05-09T00:00:00": null}       |
|        ghi|          4|{"2019-05-08T00:00:00": null, "2019-05-09T00:00:00": null}         |

Желаемый результат

+-----------+-----------+------------------------+-----------+-----------+
|         id|      site |                saledate|       key1|       key2|
+-------------------------------------------------------------------------
|        abc|          6|     2019-05-08T00:00:00|       null|       null|
|        abc|          6|     2019-05-09T00:00:00|          2|          0|
|        def|          5|     2019-05-08T00:00:00|         22|         10|
|        def|          5|     2019-05-09T00:00:00|       null|       null|
|        ghi|          4|     2019-05-08T00:00:00|       null|       null|
|        ghi|          4|     2019-05-09T00:00:00|       null|       null|

Что я пробовал:

  • explode работает только для типа Array.
new_df = old_df.withColumn('saledate', explode('sale'))
  • Я могу получить свойства каждого date, выполнив следующие действия. Однако мне придется указывать каждую дату отдельно, что не идеально.
new_df = old_df
  .withColumn('sale_collection', explode('sale.2019-05-08T00:00:00'))
  .withColumn('key1', col('sale_collection').getItem('key1')
  .withColumn('key2', col('sale_collection').getItem('key2')

1 Ответ

4 голосов
/ 27 мая 2020

Вы можете использовать from_ json, чтобы преобразовать строку в карту, а затем взорвать:

from pyspark.sql.functions import from_json

df.withColumn('sale', from_json('sale', 'map<string,array<struct<key1:int,key2:int>>>')) \
  .selectExpr('*', 'explode_outer(sale) as (saledate, keys)') \
  .selectExpr('id', 'site', 'saledate', 'inline_outer(keys)') \
  .show()
+---+----+-------------------+----+----+
| id|site|           saledate|key1|key2|
+---+----+-------------------+----+----+
|abc|   6|2019-05-08T00:00:00|null|null|
|abc|   6|2019-05-09T00:00:00|   2|   0|
|def|   5|2019-05-08T00:00:00|  22|  10|
|def|   5|2019-05-09T00:00:00|null|null|
|ghi|   4|2019-05-08T00:00:00|null|null|
|ghi|   4|2019-05-09T00:00:00|null|null|
+---+----+-------------------+----+----+

Примечание: inline_outer и inline - это встроенные функции Spark SQL для разнесения массива структур.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...