Библиотека Python для создания древовидных графиков из вложенных объектов Python (dicts)
Кто-нибудь знает о каких-либо библиотеках Python, которые позволяют вам просто и быстро передавать объект, вложенный в произвольные уровни, например, в дерево диктовок в соответствии с тем, что вы найдете в этой сущности, и можно выложить выполнимый файл графа дерева?
Простота является ключевым моментом здесь, так как я должен иметь возможность работать с людьми, которые не являются технически мыслящими.
Под деревом графов я подразумеваю что-то вроде следующего: я мог бы передать ему вложенный словарь значений, а затем создать древовидную структуру:
![]()
(источник: rubyforge.org)
Ответы
Ответ 1
поэтому библиотека, которую я рекомендую и использую для моего фрагмента кода в этом ответе, не является библиотекой python, но это удобная для python библиотека, под которой я подразумеваю, что код, использующий эту библиотеку, можно вставить в модуль python для обработки данные, и этот внешний код будет подключаться к существующему питонному коду на обоих концах, т.е. как входному, так и выходному, и я подозреваю, хотя, конечно, я не знаю, что все это на самом деле означает критерий "библиотека python". Поэтому, если вы пишете веб-приложение, этот код будет на стороне клиента. Другими словами, эта библиотека не является питоном, но работает с python.
-
его вход (почти) raw python dicts, а более конкретно json.load(a_python_dict) возвращает массив или объект json, формат, который, конечно, может распознать эта библиотека javascript; и
-
формат вывода - это либо HTML, либо SVG, а не объекты в некоторых
языковой формат
Вы можете использовать d3.js. Он имеет класс специально для рендеринга деревьев:
var tree = d3.layout.tree().size([h, w]);
В папке примеров в источнике d3 также есть несколько примеров деревьев (рабочий код), которые вы можете клонировать/загружать из приведенной выше ссылки i.
Поскольку d3 является javascript-библиотекой, ее собственный формат данных - JSON.
Базовая структура представляет собой вложенный словарь, каждый словарь, представляющий единственный node с двумя значениями, имя node и его дочерние элементы (хранящиеся в массиве), с ключом имена и дети, соответственно:
{"name": "a_root_node", "children": ["B", "C"]}
и, конечно, просто конвертировать между словарями python и JSON:
>>> d = {"name": 'A', "children": ['B', 'C']}
>>> import json as JSON
>>> dj = JSON.dumps(d)
>>> dj
'{"name": "A", "children": ["B", "C"]}'
Здесь представлено представление словаря на языке python большего дерева (десяток или около того узлов), которые я преобразовал в json, как указано выше, а затем представлен в d3 как дерево, показанное на изображении ниже:
tree = {'name': 'root', 'children': [{'name': 'node 2', 'children':
[{'name': 'node 4', 'children': [{'name': 'node 10', 'size': 7500},
{'name': 'node 11', 'size': 12000}]}, {'name': 'node 5', 'children':
[{'name': 'node 12', 'children': [{'name': 'node 16', 'size': 10000},
{'name': 'node 17', 'size': 12000}]}, {'name': 'node 13', 'size': 5000}]}]},
{'name': 'node 3', 'children': [{'name': 'node 6', 'children':
[{'name': 'node 14', 'size': 8000}, {'name': 'node 15', 'size': 9000}]},
{'name': 'node 7', 'children': [{'name': 'node 8', 'size': 10000},
{'name': 'node 9', 'size': 12000}]}]}]}
![tree represented as python dictionary rendered in d3:]()
Примечание: d3 отображается в браузере; изображение выше - всего лишь снимок экрана моего окна браузера.
Ответ 2
Я не уверен, что это совсем то, что вы имеете в виду, но это первое, что приходит на ум.
blockdiag в основном предназначен для использования в качестве автономного файлового процессора, аналогичного Graphviz (для которого существует интерфейс Python). Он принимает текстовый файл как ввод с простым синтаксисом с отбрасыванием мертвой точки и создает изображения как выходные данные.
Вы должны иметь возможность написать простую прокладку для вывода своей рекурсивной структуры dict, отформатированной для ввода в автономный blockdiag script, или импортировать необходимые внутренности пакета blockdiag и напрямую управлять выходом.
Если это звучит многообещающе, я посмотрю, могу ли я поднять код примера.
EDIT Пример кода:
def print_blockdiag(tree, parent=None):
if not parent: print('blockdiag { orientation = portrait')
for key in tree:
if parent: print(' {} -> {};'.format(parent, key))
print_blockdiag(tree[key], key)
if not parent: print('}')
Это выведет файл, который может прочитать blockdiag.
Ответ 3
Я искал похожую проблему: печатать ключи dict с вложенными dicts, где структура ключей очень периодическая.
Поэтому я написал рекурсивную функцию, которая печатает ключи каждого и каждого вложенного, , но для отдельной ветки.
Надеюсь, что следующий фрагмент кода поможет другим людям:
from itertools import zip_longest
def dictPrintKeysTopBranch(dic):
#track recursive depth
depth=dictPrintKeysTopBranch.data.get('depth',-1)+1;
dictPrintKeysTopBranch.data['depth']=depth;
#accumalte keys from nested dicts
if type(dic) is type(dict()):
listKeys=sorted(list(dic.keys()));
#save keys of current depth
dictPrintKeysTopBranch.data['listKeysDepth{}'.format(depth)]=listKeys;
#repeat for top branch
dictPrintKeysTopBranch(dic[listKeys[0]]);
#print accumalated list of keys
else:
#pad lists
lists=[];
maxlen=[];
for d in range(depth):
l=dictPrintKeysTopBranch.data['listKeysDepth{}'.format(d)];
lists.append(l);
lens = [len(s) for s in l];
maxlen.append(max(lens)+1);
i=-1;
for zipped in zip_longest(*lists, fillvalue=' '):
i=i+1;
#print(x)
row = '';
j=-1;
for z in zipped:
j=j+1;
if i==0:
row = row+ ((' {: <'+str(maxlen[j])+'} -->\\').format(z));
else :
row = row+ ((' {: <'+str(maxlen[j])+'} |').format(z));
print(row.strip('\\|->'));
dictPrintKeysTopBranch.data={};
dictPrintKeysTopBranch.data={};
Вот пример:
mydict = { 'topLv':{'secLv':{'thirdLv':{'item1':42,'item2':'foo'}}},
'topLvItem':[1,2,3],
'topLvOther':{'notPrinted':':('}
}
dictPrintKeysTopBranch(mydict)
Вывод:
topLv -->\ secLv -->\ thirdLv -->\ item1
topLvItem | | | item2
topLvOther | | |
Ответ 4
В зависимости от того, что вам нужно, но если вам нужно только для просмотра содержимого, вы можете использовать онлайн-инструмент для этого - "Форматировать форматирование питона и viewer" может отображать dict как дерево.