将数据帧放入嵌套的子字典中

2024-06-10 09:30:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个如下所示的数据框架,其中每个“级别”深入到更详细的信息中,最后一个级别有一个id值

data = [
    {'id': 1, 'level_1': 'Animals', 'level_2': 'Carnivores', 'level_3': 'Felidae', 'level_4', 'Siamese Cat'},
    {'id': 2, 'level_1': 'Animals', 'level_2': 'Carnivores', 'level_3': 'Felidae', 'level_4', 'Javanese Cat'},
    {'id': 3, 'level_1': 'Animals', 'level_2': 'Carnivores', 'level_3': 'Ursidae', 'level_4', 'Polar Bear'},
    {'id': 4, 'level_1': 'Animals', 'level_2': 'Carnivores', 'level_3': 'Canidae', 'level_4', 'Labradore Retriever'},
    {'id': 5, 'level_1': 'Animals', 'level_2': 'Carnivores', 'level_3': 'Canidae', 'level_4', 'Golden Retriever'}
]

我想把它变成一个嵌套的父/子关系字典,如下所示

var data = {
  "name": "Animals",
  "children": [
    {
      "name": "Carnivores",
      "children": [
        {
          "name": "Felidae",
          "children": [
            {
              "id": 1,
              "name": "Siamese Cat",
              "children": []
            },
            {
              "id": 2,
              "name": "Javanese Cat",
              "children": []
            }
          ]
        },
        {
          "name": "Ursidae",
          "children": [
            {
              "id": 3,
              "name": "Polar Bear",
              "children": []
            }
          ]
        },
        {
          "name": "Canidae",
          "children": [
            {
              "id": 4,
              "name": "Labradore Retriever",
              "children": []
            },
            {
              "id": 5,
              "name": "Golden Retriever",
              "children": []
            }
          ]
        }
      ]
    }
  ]
}

我已经尝试了几种方法对数据帧进行分组,并在单个行上循环,但还没有找到有效的解决方案。任何帮助都将不胜感激


Tags: 数据nameiddata级别levelcatanimals
2条回答

编辑:必须进行调整,因为结果与预期不完全一致

下面是一个产生预期输出的尝试(如果我没有犯错误,这也不会令人惊讶,因为我在途中犯了几个错误):

def pack_level(df):
    if df.columns[0] == 'id':
        return [{'id': i, 'name': name, 'children': []}
                for i, name in zip(df[df.columns[0]], df[df.columns[1]])]
    return [{'name': df.iloc[0, 0],
             'children': [entry for lst in df[df.columns[1]]
                                for entry in lst]}]

df = pd.DataFrame(data)
columns = list(df.columns[1:])
df = df.groupby(columns[:-1]).apply(pack_level)
for i in range(1, len(columns) - 1):
    df = (df.reset_index(level=-1, drop=False).groupby(columns[:-i])
                                              .apply(pack_level)
                                              .reset_index(level=-1, drop=True))

var_data = {'name': df.index[0], 'children': df.iloc[0]}

乍一看,结果似乎有点不同,但这应该只是由于排序(从打印):

{
    "children": [
        {
            "children": [
                {
                    "children": [
                        {
                            "children": [],
                            "id": 4,
                            "name": "Labradore Retriever"
                        },
                        {
                            "children": [],
                            "id": 5,
                            "name": "Golden Retriever"
                        }
                    ],
                    "name": "Canidae"
                },
                {
                    "children": [
                        {
                            "children": [],
                            "id": 1,
                            "name": "Siamese Cat"
                        },
                        {
                            "children": [],
                            "id": 2,
                            "name": "Javanese Cat"
                        }
                    ],
                    "name": "Felidae"
                },
                {
                    "children": [
                        {
                            "children": [],
                            "id": 3,
                            "name": "Polar Bear"
                        }
                    ],
                    "name": "Ursidae"
                }
            ],
            "name": "Carnivores"
        }
    ],
    "name": "Animals"
}

我已经尝试尽可能地通用,但是第一列必须命名为id(如您的示例中所示)

@Timus的答案与您的意图相似,但是您可能会遇到一些困难,因为每个级别都有一个键name和一个键children。如果这是你想要的,忽略我的回答。但是,如果您想创建一个字典,以便更轻松地搜索唯一键,您可以尝试:

df = df.set_index(['level_1', 'level_2', 'level_3', 'level_4'])

def make_dictionary(df):
    if df.index.nlevels == 1:
        return df.to_dict()

    dictionary = {}
    for key in df.index.get_level_values(0).unique():
        sub_df = df.xs(key)
        dictionary[key] = df_to_dict(sub_df)
    return dictionary

make_dictionary(df)

它需要将不同的级别设置为索引,最终您将得到一个稍微不同的字典:

{'Animals': 
    {'Carnivores': 
        {'Felidae': 
          {'id': {'Siamese Cat': 1,
                  'Javanese Cat': 2}},
         'Ursidae': 
          {'id': {'Polar Bear': 3}},
         'Canidae': 
          {'id': {'Labradore Retriever': 4, 
                  'Golden Retriever': 5}}}
    }
}

相关问题 更多 >