python - 将 JSON 键值分解为新行

标签 python dataframe apache-spark pyspark apache-spark-sql

我正在寻找转换嵌套 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'))
  • 我可以通过执行以下操作来获取每个日期的属性。但是,我必须单独指定每个日期,这并不理想。
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')

最佳答案

您可以使用from_json将字符串转换为 Map 然后爆炸:

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_outerinline是 SparkSQL 内置函数,用于分解结构数组。

关于python - 将 JSON 键值分解为新行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62032112/

相关文章:

python - 根据条件组合 Pandas 行

python - 图像中土壤颗粒分水岭以外的替代分割技术

python - 将 Pandas DataFrame 保存为 JSON 字符串

python - 有没有一种简单的方法可以消除 Python-pandas 中 DataFrame 中的重复行?

java - 为什么spark不选择证书?

python - pytest 自动化显然在测试收集阶段运行测试

python - 计算n维图像熵Python

python - 如何获取数据框列值并替换?

r - 找不到函数 "switch_lang"

hadoop - 无法在 HDP 2.5.0 中对 Oozie 运行 Spark 操作(java.lang.IllegalArgumentException : Invalid ContainerId)