2012-05-05 4 views
-1

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

Мне не удалось получить желаемый результат с .dot, потому что я не знаю, как заказать узлы. Я не возражаю, импортируя файл в yEd или другой редактор. Тем не менее, я хочу иметь возможность генерировать данные очень легко с небольшим синтаксисом.

То, на что я нацеливаюсь, является инструментом, который генерирует, например. формат .graphml из минималистских данных, таких как (A (B1 C1 C2) B2), где A - метка корня, B1 - левый ребенок корня с двумя другими детьми. Подобная сложность, как .dot или .tgf, была бы, конечно, приемлемой, но я хочу, чтобы не писать сам компилятор для генерации .graphml.

Любые идеи оценили.

Маркус Р.

+0

Что вы подразумеваете под _This работает в .dot, только если используются пустые узлы_? – marapet

+0

То есть, я должен использовать невидимые виртуальные узлы (листья), чтобы направить ребро. –

+0

При визуализации графика, почему следует избегать виртуальных узлов? – parselmouth

ответ

1

Данные, которые поставляются более или менее s-expression. Учитывая, что это формат, который вы хотите глотать, pyparsing (модуль Python) имеет s-expression parser.

Вам также понадобится библиотека графов. Я использую networkx для большей части моей работы. С Pyparsing S-выражение, синтаксический анализатор и NetworkX, следующий код глотает данные и создает дерево как орграф:

import networkx as nx 

def build(g, X): 
    if isinstance(X, list): 
     parent = X[0] 
     g.add_node(parent) 
     for branch in X[1:]: 
      child = build(g, branch) 
      g.add_edge(parent, child) 

     return parent 

    if isinstance(X, basestring): 
     g.add_node(X) 
     return X 

#-- The sexp parser is constructed by the code example at... 
#-- http://http://pyparsing.wikispaces.com/file/view/sexpParser.py 
sexpr = sexp.parseString("(A (B1 C1 C2) B2)", parseAll = True) 

#-- Get the parsing results as a list of component lists. 
nested = sexpr.asList() 

#-- Construct an empty digraph. 
dig = nx.DiGraph() 

#-- build the tree 
for component in nested: 
    build(dig, component) 

#-- Write out the tree as a graphml file. 
nx.write_graphml(dig, 'tree.graphml', prettyprint = True) 

Чтобы проверить это, я также написал дерево как .dot файл и используется для создания Graphviz следующее изображение:

(graphviz output of tree)

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

+0

Спасибо. Я не знал о сетевой библиотеке. Однако результат не совсем то, что мне нужно. В вашем примере, если вы удалите, скажем C2, то в сгенерированном новом изображении вы будете иметь вертикальную линию от B1 до C1, и, следовательно, больше не будет никаких признаков того, что C1 является правильным ребенком (а B1 не имеет левого ребенка) , Мне нужен образ, который поддерживает эту структуру. Независимо от того, парсер очень полезен. –

+0

@MarkusRother if "(A (B1 C1 C2) B2)" описывает настоящее дерево, можете ли вы предоставить аналогичную вложенную структуру для случая, когда C2 удален? Если новая вложенная структура была представлена ​​как «(A (B1 C1) B2)» - как мы можем отличить, что C1 - правильный ребенок B1, а не левый ребенок? – parselmouth

+0

@MarkusRother от чтения вашего предыдущего комментария выделяется слово «вертикальный», и в сочетании с вашим комментарием к вашему вопросу «невидимые виртуальные узлы (листья), чтобы направить ребро», суть вашего вопроса одна из генерации GraphML из вложенная структура, или это макет и визуализация (возможно) неполных деревьев? – parselmouth

Смежные вопросы