Python - 将字段和标签添加到嵌套的 json 文件

Posted

技术标签:

【中文标题】Python - 将字段和标签添加到嵌套的 json 文件【英文标题】:Python - Adding fields and labels to nested json file 【发布时间】:2017-05-03 18:27:30 【问题描述】:

我有一个如下的数据框:

Name_ID | URL                    | Count | Rating
------------------------------------------------
ABC     | www.example.com/ABC    | 10    | 5
123     | www.example.com/123    | 9     | 4
XYZ     | www.example.com/XYZ    | 5     | 2
ABC111  | www.example.com/ABC111 | 5     | 2
ABC121  | www.example.com/ABC121 | 5     | 2
222     | www.example.com/222    | 5     | 3
abc222  | www.example.com/abc222 | 4     | 2
ABCaaa  | www.example.com/ABCaaa | 4     | 2

我正在尝试按如下方式创建 JSON:


    "name": "sampledata",
    "children": [
        
            "name": 9,
            "children": [
                
                    "name": 4,
                    "children": [
                        
                            "name": "123",
                            "size": 100
                        
                    ]
                
            ]
        ,
        
            "name": 10,
            "children": [
                
                    "name": 5,
                    "children": [
                        
                            "name": "ABC",
                            "size": 100
                        
                    ]
                
            ]
        ,
        
            "name": 4,
            "children": [
                
                    "name": 2,
                    "children": [
                        
                            "name": "abc222",
                            "size": 50
                        ,
                        
                            "name": "ABCaaa",
                            "size": 50
                        
                    ]
                
            ]
        ,
        
            "name": 5,
            "children": [
                
                    "name": 2,
                    "children": [
                        
                            "name": "ABC",
                            "size": 16
                        ,
                        
                            "name": "ABC111",
                            "size": 16
                        ,
                        
                            "name": "ABC121",
                            "size": 16
                        
                    ]
                ,
                
                    "name": 3,
                    "children": [
                        
                            "name": "222",
                            "size": 50
                        
                    ]
                
            ]
        
    ]

为此:

我正在尝试在创建 json 时添加标签,例如 "name""children"

我尝试了类似的东西

results = ["name": i, "children": j for i,j in results.items()]

但我相信它不会正确标记它。

另外,添加另一个带有标签“大小”的字段,我打算根据公式计算:

(Rating*Count*10000)/number_of_children_to_the_immediate_parent

这是我的脏代码:

import pandas as pd
from collections import defaultdict
import json

data =[('ABC', 'www.example.com/ABC', 10   , 5), ('123', 'www.example.com/123', 9, 4), ('XYZ', 'www.example.com/XYZ', 5, 2), ('ABC111', 'www.example.com/ABC111', 5, 2), ('ABC121', 'www.example.com/ABC121', 5, 2), ('222', 'www.example.com/222', 5, 3), ('abc222', 'www.example.com/abc222', 4, 2), ('ABCaaa', 'www.example.com/ABCaaa', 4, 2)]

df = pd.DataFrame(data, columns=['Name', 'URL', 'Count', 'Rating'])

gp = df.groupby(['Count'])

dict_json = "name": "flare"
children = []

for name, group in gp:
    temp = 
    temp["name"] = name
    temp["children"] = []

    rgp = group.groupby(['Rating'])
    for n, g in rgp:
        temp2 = 
        temp2["name"] = n
        temp2["children"] = g.reset_index().T.to_dict().values()
        for t in temp2["children"]:
            t["size"] = (t["Rating"] * t["Count"] * 10000) / len(temp2["children"])
            t["name"] = t["Name"]
            del t["Count"]
            del t["Rating"]
            del t["URL"]
            del t["Name"]
            del t["index"]
        temp["children"].append(temp2)
    children.append(temp)

dict_json["children"] = children

print json.dumps(dict_json, indent=4)

虽然上面的代码确实打印了我需要的东西,但我正在寻找更高效、更简洁的方法来做同样的事情,主要是因为实际的数据集可能更加嵌套和复杂。任何帮助/建议将不胜感激。

【问题讨论】:

您是否尝试过使用 dataframe.to_json() 函数?这应该符合您的需求:) The official pandas documentation 是的,我做到了!但是我发现很难将类似于链接中的 json 引入 :(。基本上将它们分组为子项。 您能以您想要的方式输入一个小样本 JSON 格式的输出吗? (我看不出你会如何在这个示例数据框中划分孩子) 所需的 json 无法通过 pandas 的方法获得。它需要了解需要哪些数据并考虑从何处获取数据。你只是发布了一个问题“嘿,我想要这个。我怎么得到它?”这不是 *** 的用途。它在这里帮助程序员(初学者和有经验的人)解决编程问题。我建议您实际上尝试自己解决这个问题,然后回来展示您尝试过的内容。 @piRSquared 很抱歉造成沟通不畅。我在问题的编辑部分添加了。我正在尝试分组并生成 json。由于某些原因,这对初学者来说并不容易。 【参考方案1】:

设置

from io import StringIO
import pandas as pd

txt = """Name_ID,URL,Count,Rating
ABC,www.example.com/ABC,10,5
123,www.example.com/123,9,4
XYZ,www.example.com/XYZ,5,2
ABC111,www.example.com/ABC111,5,2
ABC121,www.example.com/ABC121,5,2
222,www.example.com/222,5,3
abc222,www.example.com/abc222,4,2
ABCaaa,www.example.com/ABCaaa,4,2"""

df = pd.read_csv(StringIO(txt))

size 预先计算它

df['size'] = df.Count.mul(df.Rating) \
                     .mul(10000) \
                     .div(df.groupby(
                        ['Count', 'Rating']).Name_ID.transform('count')
                     ).astype(int)

解决方案 创建递归函数

def h(d):
    if isinstance(d, pd.Series): d = d.to_frame().T
    rec_cond = d.index.nlevels > 1 or d.index.nunique() > 1
    return 'name': str(d.index[0]), 'size': str(d['size'].iloc[0]) if not rec_cond else \
        [dict(name=str(n), children=h(g.xs(n))) for n, g in d.groupby(level=0)]

演示

import json

my_dict = dict(name='flare', children=h(df.set_index(['Count', 'Rating', 'Name_ID'])))

json.dumps(my_dict)

'"name": "flare", "children": ["name": "4", "children": ["name": "2", "children": ["name" :“ABCaaa”,“儿童”:“名称”:“ABCaaa”,“大小”:“40000”,“名称”:“abc222”,“儿童”:“名称”:“abc222”, “大小”:“40000”]],“名称”:“5”,“孩子”:[“名称”:“2”,“孩子”:[“名称”:“ABC111” ,“孩子”:“名称”:“ABC111”,“大小”:“33333”,“名称”:“ABC121”,“孩子”:“名称”:“ABC121”,“大小”: "33333", "name": "XYZ", "children": "name": "XYZ", "size": "33333"], "name": "3", "孩子”:“姓名”:“222”,“大小”:“150000”],“姓名”:“9”,“孩子”:[“姓名”:“4”,“孩子” : "name": "123", "size": "360000"], "name": "10", "children": ["name": "5", "children": “名称”:“ABC”,“大小”:“500000”]]'

my_dict

'children': ['children': ['children': ['children': 'name': 'ABCaaa',
        'size': '40000',
       'name': 'ABCaaa',
      'children': 'name': 'abc222', 'size': '40000', 'name': 'abc222'],
     'name': '2'],
   'name': '4',
  'children': ['children': ['children': 'name': 'ABC111', 'size': '33333',
       'name': 'ABC111',
      'children': 'name': 'ABC121', 'size': '33333', 'name': 'ABC121',
      'children': 'name': 'XYZ', 'size': '33333', 'name': 'XYZ'],
     'name': '2',
    'children': 'name': '222', 'size': '150000', 'name': '3'],
   'name': '5',
  'children': ['children': 'name': '123', 'size': '360000', 'name': '4'],
   'name': '9',
  'children': ['children': 'name': 'ABC', 'size': '500000', 'name': '5'],
   'name': '10'],
 'name': 'flare'

【讨论】:

【参考方案2】:

一个很有趣的问题,一个很好的问题!

您可以通过重新组织循环内的代码并使用list comprehensions 来改进您的方法。无需删除东西并在循环中引入临时变量:

dict_json = "name": "flare"

children = []
for name, group in gp:
    temp = "name": name, "children": []

    rgp = group.groupby(['Rating'])
    for n, g in rgp:
        temp["children"].append(
            "name": n,
            "children": [
                "name": row["Name"],
                 "size": row["Rating"] * row["Count"] * 10000 / len(g)
                for _, row in g.iterrows()
            ]
        )

    children.append(temp)

dict_json["children"] = children

或者,一个“包装”的版本:

dict_json = 
    "name": "flare", 
    "children": [
        
            "name": name, 
            "children": [
                
                    "name": n,
                    "children": [
                        
                            "name": row["Name"],
                            "size": row["Rating"] * row["Count"] * 10000 / len(g)
                         for _, row in g.iterrows()
                    ]
                 for n, g in group.groupby(['Rating'])
            ]
         for name, group in gp
    ]

我正在为您打印以下字典示例输入数据帧:


    "name": "flare", 
    "children": [
        
            "name": 4, 
            "children": [
                
                    "name": 2, 
                    "children": [
                        
                            "name": "abc222", 
                            "size": 40000
                        , 
                        
                            "name": "ABCaaa", 
                            "size": 40000
                        
                    ]
                
            ]
        , 
        
            "name": 5, 
            "children": [
                
                    "name": 2, 
                    "children": [
                        
                            "name": "XYZ", 
                            "size": 33333
                        , 
                        
                            "name": "ABC111", 
                            "size": 33333
                        , 
                        
                            "name": "ABC121", 
                            "size": 33333
                        
                    ]
                , 
                
                    "name": 3, 
                    "children": [
                        
                            "name": "222", 
                            "size": 150000
                        
                    ]
                
            ]
        , 
        
            "name": 9, 
            "children": [
                
                    "name": 4, 
                    "children": [
                        
                            "name": "123", 
                            "size": 360000
                        
                    ]
                
            ]
        , 
        
            "name": 10, 
            "children": [
                
                    "name": 5, 
                    "children": [
                        
                            "name": "ABC", 
                            "size": 500000
                        
                    ]
                
            ]
        
    ]

【讨论】:

【参考方案3】:

如果我理解正确,您不希望将 groupby 放入嵌套的 json 中,如果是这种情况,那么您可以使用 pandas groupby 并将其转换为嵌套的列表列表:

lol = pd.DataFrame(df.groupby(['Count','Rating'])\
               .apply(lambda x: list(x['Name_ID']))).reset_index().values.tolist()

lol 应该是这样的:

[['10', '5', ['ABC']],
['4', '2', ['abc222', 'ABCaaa']],
['5', '2', ['XYZ ', 'ABC111', 'ABC121']],
['5', '3', ['222 ']],
['9', '4', ['123 ']]]

之后,您可以遍历 lol 以将其放入 dict 中,但由于您想设置嵌套项目,您必须使用自动激活(检查一下):

class autovividict(dict):
   def __missing__(self, key):
      value = self[key] = type(self)()
      return value

d = autovividict()
for l in lol:
    d[l[0]][l[1]] = l[2]

现在您可以使用 json 包进行打印和导出:

print json.dumps(d,indent=2)

如果您需要多个 groupby,您可以将您的组与 pandas 连接,转换为 lol,删除任何 nans,然后循环,如果一个完整的示例可以帮助,请告诉我。

【讨论】:

我添加了更多关于我的方法的解释(当然是基于你在这里的建议和其他地方的另一个 SO 答案)以及我到底在哪里卡住了。任何建议将不胜感激。

以上是关于Python - 将字段和标签添加到嵌套的 json 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何将嵌套字段添加到我的 BigQuery 表架构?

YAML - 转储没有类型/标签的嵌套对象

Elasticsearch - 将普通字段过滤器添加到嵌套字段聚合

将条件匹配的字段添加到嵌套数组

python中使用squarify包可视化treemap图:treemap将分层数据显示为一组嵌套矩形自定义设置每一个数据格的颜色添加数值数值标签自定义设置边框的色彩

将标签字段添加到 asp.net 网页