Построить дерево с помощью Python

Я новичок в python и пытаюсь построить дерево с отношением родитель-ребенок с помощью python. Мне нелегко это сделать:

Фрейм данных:

data = [['root','Parent1','Children1','Grand Childern 1','Great Grand Childern 1'],['root','Parent1','Children2','Grand Childern 1','Great Grand Childern 1'],['root','Parent1','Children2','Grand Childern 2','Great Grand Childern 1'],['root','Parent2','Children1','Grand Childern 1','Great Grand Childern 1'],['root','Parent2','Children2','Grand Childern 1','Great Grand Childern 1']]

df=pd.DataFrame(data,columns=['LEVEL 1','LEVEL 2','LEVEL 3','LEVEL 4','LEVEL 5'])

И я пытаюсь преобразовать в формат дерева JSON, как показано ниже:

{
"name": "root",
"children": [{ 
    "name": "Parent1",
    "children": [{ 
        "name": "Children1" ,
        "children":[{
            "name":"Grand Children1",
            "children":[{
                "name":"Great Grand Children1"
                }]
            }]},
    { 
        "name": "Children2" , 
        "children":[{
          "name":"Grand Children1",
                "children":[{"name":"Great Grand Children1"}],
          "name":"Grand Children2",
                "children":[{"name":"Great Grand Children1"}]}
          ] }
    ]
  },
  { 
    "name": "Parent2",
    "children": [
      { 
          "name": "Children1" ,
          "children":[{"name":"Grand Children1",
                        "children":[{"name":"Great Grand Children1"}]}] },
      { 
          "name": "Children2" , 
          "children":[{
          "name":"Grand Children1","children":[{"name":"Great Grand Children1"}],
          "name":"Grand Children1","children":[{"name":"Great Grand Children2"}]}
          ] }
    ]
  }]
}

DataFrame:

введите здесь описание изображения

Я ценю, если кто-нибудь может мне помочь.


person Sanjay Chintha    schedule 07.05.2020    source источник
comment
Было бы хорошо показать вам, где находится ваш код, и объяснить, что именно с ним не работает. В противном случае может показаться, что вы хотите, чтобы мы сделали за вас всю работу, чего мы, конечно же, делать не будем!   -  person Thierry Lathuille    schedule 07.05.2020


Ответы (3)


Вы можете использовать рекурсию с collections.defaultdict:

from collections import defaultdict
def to_tree(d):
   _d = defaultdict(list)
   for a, *b in d:
      _d[a].append(b)
   return [{'name':a, 'children':to_tree(k)} if (k:=list(filter(None, b))) else \
                    {'name':a} for a, b in _d.items()]

data = [['root','Parent1','Children1','Grand Childern 1','Great Grand Childern 1'],['root','Parent1','Children2','Grand Childern 1','Great Grand Childern 1'],['root','Parent1','Children2','Grand Childern 2','Great Grand Childern 1'],['root','Parent2','Children1','Grand Childern 1','Great Grand Childern 1'],['root','Parent2','Children2','Grand Childern 1','Great Grand Childern 1']]

import json
print(json.dumps(to_tree(data), indent=4))

Выход:

[
  {
    "name": "root",
    "children": [
        {
            "name": "Parent1",
            "children": [
                {
                    "name": "Children1",
                    "children": [
                        {
                            "name": "Grand Childern 1",
                            "children": [
                                {
                                    "name": "Great Grand Childern 1"
                                }
                            ]
                        }
                    ]
                },
                {
                    "name": "Children2",
                    "children": [
                        {
                            "name": "Grand Childern 1",
                            "children": [
                                {
                                    "name": "Great Grand Childern 1"
                                }
                            ]
                        },
                        {
                            "name": "Grand Childern 2",
                            "children": [
                                {
                                    "name": "Great Grand Childern 1"
                                }
                            ]
                        }
                    ]
                }
            ]
        },
        {
            "name": "Parent2",
            "children": [
                {
                    "name": "Children1",
                    "children": [
                        {
                            "name": "Grand Childern 1",
                            "children": [
                                {
                                    "name": "Great Grand Childern 1"
                                }
                            ]
                        }
                    ]
                },
                {
                    "name": "Children2",
                    "children": [
                        {
                            "name": "Grand Childern 1",
                            "children": [
                                {
                                    "name": "Great Grand Childern 1"
                                }
                            ]
                        }
                    ]
                 }
             ]
          }
      ]
   }
]

Решение без выражения присваивания Python3.8:

from collections import defaultdict
def to_tree(d):
   _d = defaultdict(list)
   for a, *b in d:
     _d[a].append(b)
   vals = [[a, list(filter(None, b))] for a, b in _d.items()]
   return [{'name':a, 'children':to_tree(b)} if b else {'name':a} for a, b in vals]
person Ajax1234    schedule 07.05.2020
comment
строка: return [{'name': a, 'children': to_tree (k)} if (k: = list (filter (None, b))) else \ {'name': a} для a, b в _d .items ()] не работает, это выдает мне синтаксическую ошибку на "k" - person Sanjay Chintha; 08.05.2020
comment
@ImSanjay k используется в выражении присваивания, которое доступно только в Python3.8. Пожалуйста, ознакомьтесь с моими недавними изменениями, поскольку я добавил решение, которое будет совместимо с ‹версиями Python3.8. - person Ajax1234; 08.05.2020
comment
все еще выдает ошибку AttributeError: объект 'list' не имеет атрибута 'items' - person Sanjay Chintha; 08.05.2020
comment
можем ли мы добавить имя столбца после атрибута «имя»? @ Ajax1234 - person Sanjay Chintha; 10.06.2020

Если это не обязательно из библиотеки "Pandas", вы можете использовать библиотеку 'anytree'. для создания своего дерева и "JSON Exporter" для его экспорта в JSON.

person shu    schedule 07.05.2020

В качестве промежуточного шага вы можете захотеть преобразовать свой список списков (который в настоящее время не входит в структуру дерева, а скорее определяет отдельные вертикальные ветви дерева) в дерево словарных статей, где каждый узел содержит ссылки на все свои дочерние узлы.

Использование dict для построения вашего дерева из вашего списка списков значительно упрощает проверку того, что все дочерние элементы любого данного узла попадают в нужное место (то есть сгруппированы вместе под этим узлом):

>>> data = [
    ['root', 'Parent1', 'Children1', 'Grand Childern 1', 'Great Grand Childern 1'],
    ['root', 'Parent1', 'Children2', 'Grand Childern 1', 'Great Grand Childern 1'],
    ['root', 'Parent1', 'Children2', 'Grand Childern 2', 'Great Grand Childern 1'],
    ['root', 'Parent2', 'Children1', 'Grand Childern 1', 'Great Grand Childern 1'],
    ['root', 'Parent2', 'Children2', 'Grand Childern 1', 'Great Grand Childern 1']
]
>>> tree = {}
>>> for row in data:
...     node = tree
...     for cell in row:
...         node = node.setdefault(cell, {})
...
>>> tree
{'root': {
    'Parent1': {
        'Children1': {
            'Grand Childern 1': {
                'Great Grand Childern 1': {}
            }
        }, 
        'Children2': {
            'Grand Childern 1': {
                'Great Grand Childern 1': {}
            }, 
            'Grand Childern 2': {
                'Great Grand Childern 1': {}
            }
        }
    }, 
    'Parent2': {
        'Children1': {
            'Grand Childern 1': {
                'Great Grand Childern 1': {}
            }
        }, 
        'Children2': {
            'Grand Childern 1': {
                'Great Grand Childern 1': {}
            }
        }
    }
}}

Теперь, когда у вас есть все в структуре, которая представляет собой реальное дерево, его должно быть просто преобразовать в любой более конкретный формат, который вам нужен (например, желаемый JSON).

person Samwise    schedule 07.05.2020