使用 normalize 展平三重嵌套 JSON

Posted

技术标签:

【中文标题】使用 normalize 展平三重嵌套 JSON【英文标题】:Flatten triple-nested JSON with normalize 【发布时间】:2019-12-10 02:59:09 【问题描述】:

我正在尝试展平以下内容,但它仅适用于非三重嵌套 JSON。

工作代码:

导入 json

import pandas as pd 
from pandas.io.json import json_normalize

data = ['masterName': 'AAAAAAAAAAA',
         'shortname': 'AA',
         'info': 
              'name': 'randomka'
         ,
         'mainNames': ['date': '2019-05-16', 'NumberOne': 1111,
                       'date': '2019-06-22', 'NumberOne': 2222]
       ]

result = json_normalize(data, 'mainNames', ['masterName', 'shortname',
                                          ['info', 'name']],errors='ignore')

不工作:

data2 = ["masterName": "AAAAAAAAAAA",
          "mainNames": [
            
                "numbers": [
                        "date": "2019-05-16",
                        "NumberOne": 222],
                "name": "randomka"
            ,
            
                "numbers": [
                        "date": "2019-05-16",
                        "NumberOne": 222],
                "name": "randomka"
            
        ]
    ]

    json_normalize(data2, 'mainNames', ['masterName'],errors='ignore')

返回时:

我在json_normalize 代码中尝试了替代record_pathsmetas,但我无法使其适用于这个三重嵌套的JSON。换句话说,我不能一口气读完所有的专栏。

我尝试过的替代方案很有效并且看起来很接近:

json_normalize(data2, ['mainNames','numbers'], ['masterName'],errors='ignore') 

输出几乎是一个 Excel 视图,其中包含列中的数据。根据评论请求的预期视图:

UPD:数据可能有多个数字分支:

data2 = ["masterName": "AAAAAAAAAAA",
          "mainNames": [
            
                "numbers": [
                        "date": "2019-05-16",
                        "NumberOne": 222],
                "name": "randomka"
            ,
            
                "numbers": [
                        "date": "2019-05-16",
                        "NumberOne": 222,

                        "date": "2019-07-01",
                        "NumberOne": 341],
                "name": "randomka"
            
        ]
    ]

【问题讨论】:

你能分享一下预期的输出吗?我不熟悉这个过程正常化。我敢肯定,分享预期的输出也会对其他人有所帮助。无论如何,为这个问题制作自己的功能是否可以接受?我觉得这可能需要更少的时间。 【参考方案1】:

正如@Aayush Mahajan 在 cmets 中所建议的那样,定义自己的函数可能更简单。这是一个与data2合作的人:

out = []
data2 = data2[0]                                    # Remove first level
for main in data2["mainNames"]:                     # Iterate "mainNames"
    sub_dict = "masterName": data2['mainNames']   # Init new dict (df row) with "mainNames"
    sub_dict.update(main["numbers"][0])             # Add all fields from "numbers"
    sub_dict["name"] = main["name"]                 # Add "name" field

    out.append(sub_dict)                            # append sud dict to list outputs

print(out)
# ['masterName': 'AAAAAAAAAAA', 'date': '2019-05-16', 'NumberOne': 222, 'name': 'randomka',
#  'masterName': 'AAAAAAAAAAA', 'date': '2019-05-16', 'NumberOne': 222, 'name': 'randomka']

# create Dataframe with from_dict
df = pd.DataFrame().from_dict(out)
print(df)
#     masterName        date  NumberOne      name
# 0  AAAAAAAAAAA  2019-05-16        222  randomka
# 1  AAAAAAAAAAA  2019-05-16        222  randomka

更新: 您可以添加一个内部 loop 来迭代 numbers 字段:

out = []
data2 = data2[0]                                    # Remove first level
for main in data2["mainNames"]:                     # Iterate "mainNames"
    for numbers in main["numbers"]:
        sub_dict = "masterName": data2['masterName']  # Init new dict (df row) with "mainNames"
        sub_dict.update(numbers)                        # Add all fields from "numbers"
        sub_dict["name"] = main["name"]                 # Add "name" field

        out.append(sub_dict)                            # append sud dict to list outputs

print(out)
# ['masterName': 'AAAAAAAAAAA', 'date': '2019-05-16', 'NumberOne': 222, 'name': 'randomka',
#  'masterName': 'AAAAAAAAAAA', 'date': '2019-05-16', 'NumberOne': 222, 'name': 'randomka',
#  'masterName': 'AAAAAAAAAAA', 'date': '2019-07-01', 'NumberOne': 341, 'name': 'randomka']

df = pd.DataFrame().from_dict(out)
print(df)
#    NumberOne        date   masterName      name
# 0        222  2019-05-16  AAAAAAAAAAA  randomka
# 1        222  2019-05-16  AAAAAAAAAAA  randomka
# 2        341  2019-07-01  AAAAAAAAAAA  randomka

同样,它仍在使用初始的data2

希望有帮助!

【讨论】:

当有多个数字数组时不起作用。 @Apolo Radomer 我根据您提供的样本回答。如果您的数据实际上不同,请分享最坏的情况或添加详细信息。 我尝试使用 for 循环进行很多更改,但对我不起作用。我已经用更新的 JSON 更新了问题。 我是如此接近。我在循环之外有sub_dict = "masterName": data2['masterName']

以上是关于使用 normalize 展平三重嵌套 JSON的主要内容,如果未能解决你的问题,请参考以下文章

Pandas json_normalize 不会展平所有嵌套字段

pandas json_normalize 所有列都有嵌套字典展平

如何展平多级/嵌套 JSON?

用嵌套列表和嵌套字典列表展平一个非常大的 Json

规范化/展平非常深的嵌套 JSON(其中名称和属性在各个级别中相同)

在python中展平JSON数据框