Python中JSON秒变Dataframe的示例
创始人
2024-12-27 12:41:26
0次

调用API和文档数据库会返回嵌套的JSON对象,当我们使用Python尝试将嵌套结构中的键转换为列时,数据加载到pandas中往往会得到如下结果:

df = pd.DataFrame.from_records(results [“ issues”],columns = [“ key”,“ fields”])
说明:这里results是一个大的字典,issues是results其中的一个键,issues的值为一个嵌套JSON对象字典的列表,后面会看到JSON嵌套结构。

问题在于API返回了嵌套的JSON结构,而我们关心的键在对象中确处于不同级别。

嵌套的JSON结构张成这样的。

而我们想要的是下面这样的。

下面以一个API返回的数据为例,API通常包含有关字段的元数据。假设下面这些是我们想要的字段。

  • key:JSON密钥,在第一级的位置。

  • summary:第二级的“字段”对象。

  • status name:第三级位置。

  • statusCategory name:位于第4个嵌套级别。

如上,我们选择要提取的字段在issues列表内的JSON结构中分别处于4个不同的嵌套级别,一环扣一环。

{
  "expand": "schema,names",
  "issues": [
    {
      "fields": {
        "issuetype": {
          "avatarId": 10300,
          "description": "",
          "id": "10005",
          "name": "New Feature",
          "subtask": False
        },
        "status": {
          "description": "A resolution has been taken, and it is awaiting verification by reporter. From here issues are either reopened, or are closed.",
          "id": "5",
          "name": "Resolved",
          "statusCategory": {
            "colorName": "green",
            "id": 3,
            "key": "done",
            "name": "Done",
          }
        },
        "summary": "Recovered data collection Defraglar $MFT problem"
      },
      "id": "11861",
      "key": "CAE-160",
    },
    {
      "fields": { 
... more issues],
  "maxResults": 5,
  "startAt": 0,
  "total": 160
}

一个不太好的解决方案

一种选择是直接撸码,写一个查找特定字段的函数,但问题是必须对每个嵌套字段调用此函数,然后再调用.apply到DataFrame中的新列。

为获取我们想要的几个字段,首先我们提取fields键内的对象至列:

df = (
    df["fields"]
    .apply(pd.Series)
    .merge(df, left_index=True, right_index = True)
)

从上表看出,只有summary是可用的,issuetype、status等仍然埋在嵌套对象中。

下面是提取issuetype中的name的一种方法。

# 提取issue type的name到一个新列叫"issue_type"
df_issue_type = (
    df["issuetype"]
    .apply(pd.Series)
    .rename(columns={"name": "issue_type_name"})["issue_type_name"]
)
df = df.assign(issue_type_name = df_issue_type)

像上面这样,如果嵌套层级特别多,就需要自己手撸一个递归来实现了,因为每层嵌套都需要调用一个像上面解析并添加到新列的方法。

对于编程基础薄弱的朋友,手撸一个其实还挺麻烦的,尤其是对于数据分析师,着急想用数据的时候,希望可以快速拿到结构化的数据进行分析。

下面东哥分享一个pandas的内置解决方案。

内置的解决方案

pandas中有一个牛逼的内置功能叫 .json_normalize。

pandas的文档中提到:将半结构化JSON数据规范化为平面表。

前面方案的所有代码,用这个内置功能仅需要3行就可搞定。步骤很简单,懂了下面几个用法即可。

确定我们要想的字段,使用 . 符号连接嵌套对象。

将想要处理的嵌套列表(这里是results["issues"])作为参数放进 .json_normalize 中。

过滤我们定义的FIELDS列表。

FIELDS = ["key", "fields.summary", "fields.issuetype.name", "fields.status.name", "fields.status.statusCategory.name"]
df = pd.json_normalize(results["issues"])
df[FIELDS]

没错,就这么简单。

其它操作

记录路径

除了像上面那样传递results["issues"]列表之外,我们还使用record_path参数在JSON对象中指定列表的路径。

# 使用路径而不是直接用results["issues"]
pd.json_normalize(results, record_path="issues")[FIELDS]

自定义分隔符

还可以使用sep参数自定义嵌套结构连接的分隔符,比如下面将默认的“.”替换“-”。

### 用 "-" 替换默认的 "."
FIELDS = ["key", "fields-summary", "fields-issuetype-name", "fields-status-name", "fields-status-statusCategory-name"]
pd.json_normalize(results["issues"], sep = "-")[FIELDS]

控制递归

如果不想递归到每个子对象,可以使用max_level参数控制深度。在这种情况下,由于statusCategory.name字段位于JSON对象的第4级,因此不会包含在结果DataFrame中。

# 只深入到嵌套第二级
pd.json_normalize(results, record_path="issues", max_level = 2)

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...