首页 > 解决方案 > 如何将以下 JSON(深度嵌套)加载到 DataFrame?

问题描述

JSON 示例如下所示:

{
  "AN": {
    "dates": {
      "2020-03-26": {
        "delta": {
          "confirmed": 1
        },
        "total": {
          "confirmed": 1
        }
      }
     }
    },
    
    "KA": {
        "dates": {
          "2020-03-09": {
            "delta": {
                "confirmed": 1
        },
        "total": {
          "confirmed": 1
        }
      },
      "2020-03-10": {
        "delta": {
          "confirmed": 3
        },
        "total": {
          "confirmed": 4
        }
      }
     }
    }
}

我想将它加载到 DataFrame 中,以便将状态名称(AN、KA)表示为行名称,并将日期和嵌套条目表示为列。

任何实现这一目标的提示将不胜感激。[我知道 json_normalize,但我还没有弄清楚如何解决它。]

我期待的输出大致如下图所示:

预期数据帧

标签: jsonpython-3.xpandasweb-scraping

解决方案


你能用你想到的 DataFrame 更新你的帖子吗?更容易理解你想要什么。

此外,如果您无法使其以现在的方式工作,有时最好重塑您的数据。

更新:

在您更新之后,您可以执行以下操作。

  • 你需要重塑你的数据,正如我所说,当你无法达到你想要的结果时,最好从另一个角度看待问题。例如(并且从您共享的示例中)“日期”键是没有意义的,因为其他键已经是日期并且没有其他键处于同一级别。
  • 实现您想要的一种方法是使用MultiIndex,它将帮助您按照您想要的方式对数据进行分组。例如,要使用它,您可以创建所需的所有索引并将相关值存储在字典中。

例子 :

如果您拥有的唯一索引是('2020-03-26', 'delta', 'confirmed')您应该拥有values = {'AN' : [1], 'KA':None}

然后你只需要创建你的 DataFrame 并转置它。

我快速尝试了一下,并想出了一段应该可以工作的代码。如果您正在寻找性能,我认为这不会成功。

import pandas as pd

# d is the sample you shared

index = [[],[],[]]
values = {}
# Get all the dates
dates = [date for c in d.keys() for date in d[c]['dates'].keys() ]

for country in d.keys():
    # For each country we create an array containing all 6 values for each date
    # (missing values as None)
    values[country] = []
    for date in dates:
        if date in d[country]['dates']:
            for method in ['delta', 'total']:
                for step in ['confirmed', 'recovered', 'tested']:
                    # Incrementing indices 
                    index[0].append(date)
                    index[1].append(method) 
                    index[2].append(step)
                    if step in value.keys():
                        values[country].append(deepcopy(d[country]['dates'][date][method][step]))
                    else : 
                        values[country].append(None)
        # When country does not have a date fill with None
        else : 
            for method in ['delta', 'total']:
                for step in ['confirmed', 'recovered', 'tested']:
                    index[0].append(date)
                    index[1].append(method) 
                    index[2].append(step)
                    values[country].append(None)

# Removing duplicates introduced because we added n_countries times
# the indices 
# 3 is the number of steps
# 2 is the number of methods

number_of_rows = 3*2*len(dates)
index[0] = index[0][:number_of_rows]
index[1] = index[1][:number_of_rows]
index[2] = index[2][:number_of_rows]

df = pd.DataFrame(values, index=index).T

这是我输出的转置数据帧的内容:

结果

希望这可以帮到你


推荐阅读