Как лучше всего нарисовать большой график с помощью graphvis?

Мне нужно нарисовать большой набор данных на изображении, я использовал командные строки graphvis со всеми доступными инструментами (точка, neato, twopi и т. Д.), Но результат не читается и содержит перекрытия.

Мне нужно отобразить узлы с метками по краям, с минимальным перекрытием, чтобы график можно было читать, а также печатать на бумаге формата А4 или А3.

Я использовал параметры overlap=false, splines=true в neato и тот же результат перекрытия.

Вот набор данных:

graph {
    graph [ bgcolor=ivory2, overlap=false, splines=true, ranksep ="2.75"]
    {node [width=1,height=1,shape=circle,style=filled,color=skyblue] "ECNY" }
    edge [ len=2, sep=5] 
    "DANA" -- "HMRN" -- "ECNY" -- "NORI" -- "MAJZ" -- "RSFH" -- "DANA" [label ="LD1-25-A01",  penwidth =3 , color="#156163"]
    "DANA" -- "HMRN" -- "ECNY" -- "NORI" -- "MAJZ" -- "RSFH" -- "DANA" [label ="LD1-25-A02",  penwidth =3 , color="#30a1f9"]
    "DANA" -- "MAJZ" -- "ECNY" -- "HMRN" -- "DANA" [label ="LD1-25-A03",  penwidth =3 , color="#ec591d"]
    "DANA" -- "MAJZ" -- "ECNY" -- "HMRN" -- "DANA" [label ="LD1-25-A04",  penwidth =3 , color="#263a5f"]
    "DANA" -- "ECNY" -- "DANA" [label ="LD3-25-A02",  penwidth =3 , color="#a3517c"]
    "HMRN" -- "ECNY" -- "MAJZ" -- "DANA" -- "HMRN" [label ="LD1-25-H01",  penwidth =3 , color="#800d83"]
    "HMRN" -- "ECNY" -- "MAJZ" -- "DANA" -- "TWRN" -- "HMRN" [label ="LD1-25-H02",  penwidth =3 , color="#89e15a"]
    "HMRN" -- "ECNY" -- "MAJZ" -- "DANA" -- "TWRN" -- "HMRN" [label ="LD3-25-H03",  penwidth =3 , color="#74ed0e"]
    "HMRN" -- "ECNY" -- "HMRN" [label ="JED-10-H08",  penwidth =3 , color="#e8e786"]
    "HMRN" -- "ECNY" -- "MAJZ" -- "DANA" -- "HMRN" [label ="LD1-25-H04",  penwidth =3 , color="#e1f559"]
    "ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-A02",  penwidth =3 , color="#8f7964"]
    "ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-A03",  penwidth =3 , color="#9058f0"]
    "ECNY" -- "HMRN" -- "SBCB" -- "ECNY" [label ="JED-10-A04",  penwidth =3 , color="#b537b7"]
    "ECNY" -- "HMRN" -- "SBCB" -- "ECNY" [label ="JED-10-A05",  penwidth =3 , color="#fc2c2a"]
    "ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-A06",  penwidth =3 , color="#36309c"]
    "ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-A07",  penwidth =3 , color="#25a571"]
    "ECNY" -- "OBHR" -- "ECNY" [label ="JED-10-A26",  penwidth =3 , color="#1a6077"]
    "ECNY" -- "2820" -- "ECNY" [label ="JED-25-A03",  penwidth =3 , color="#8bce8c"]
    "ECNY" -- "2138" -- "2129" -- "ECNY" [label ="JED-25-A04",  penwidth =3 , color="#9b9afa"]
    "ECNY" -- "2017" -- "2013" -- "ECNY" [label ="JED-25-A05",  penwidth =3 , color="#5ea9aa"]
    "ECNY" -- "2027" -- "2128" -- "ECNY" [label ="JED-25-A22",  penwidth =3 , color="#c0c4d4"]
    "ECNY" -- "2130" -- "2137" -- "ECNY" [label ="JED-25-A27",  penwidth =3 , color="#781ce0"]
    "ECNY" -- "DANA" -- "ECNY" [label ="LD3-25-A01",  penwidth =3 , color="#fd5c5a"]
    "ECNY" -- "HMRN" -- "ZJ01" -- "ECNY" [label ="JED-10-H03",  penwidth =3 , color="#32e13b"]
    "ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-H04",  penwidth =3 , color="#487f94"]
    "ECNY" -- "2341" -- "2235" -- "2233" -- "ECNY" [label ="JED-10-H05",  penwidth =3 , color="#82ae2d"]
    "ECNY" -- "HMRN" -- "SBCB" -- "ECNY" [label ="JED-10-H06",  penwidth =3 , color="#f4651c"]
    "ECNY" -- "HMRN" -- "SBCB" -- "ECNY" [label ="JED-10-H07",  penwidth =3 , color="#23dd41"]
    "ECNY" -- "HMRN" -- "OBHR" -- "ECNY" [label ="JED-10-H37",  penwidth =3 , color="#521f43"]
    "ECNY" -- "PROJECT" -- "ECNY" [label ="JED-10-H49",  penwidth =3 , color="#0a4bf1"]
    "ECNY" -- "2234" -- "2246" -- "2245" -- "2320" -- "ECNY" [label ="JED-25-H01",  penwidth =3 , color="#6127e4"]
    "ECNY" -- "2842" -- "2030" -- "ECNY" [label ="JED-25-H03",  penwidth =3 , color="#ce1f98"]
    "ECNY" -- "2170" -- "2166" -- "ECNY" [label ="JED-25-H06",  penwidth =3 , color="#aeb0ce"]
    "ECNY" -- "2158" -- "2144" -- "ECNY" [label ="JED-25-H11",  penwidth =3 , color="#9ef618"]
    "ECNY" -- "5824" -- "2011" -- "ECNY" [label ="JED-25-H15",  penwidth =3 , color="#b2d524"]
    "ECNY" -- "2010" -- "2830" -- "2198" -- "ECNY" [label ="JED-25-H16",  penwidth =3 , color="#53e7ae"]
    "ECNY" -- "2179" -- "ECNY" [label ="JED-25-H17",  penwidth =3 , color="#149169"]
    "ECNY" -- "2211" -- "ECNY" [label ="JED-25-H19",  penwidth =3 , color="#15a51b"]
    "ECNY" -- "2316" -- "ECNY" [label ="JED-25-H20",  penwidth =3 , color="#e91d18"]
    "ECNY" -- "2203" -- "ECNY" [label ="JED-25-H22",  penwidth =3 , color="#38a23a"]
    "ECNY" -- "SBCB" -- "JFCC" -- "ECNY" [label ="JED-25-H33",  penwidth =3 , color="#a1abf4"]
    "ECNY" -- "HMRN" -- "ECNY" [label ="JED-25-H41",  penwidth =3 , color="#c14ff8"]
    "ECNY" -- "TAIF" -- "SNFN" -- "NORI" -- "ECNY" [label ="LD1-10-H04",  penwidth =3 , color="#75fb4f"]
    "ECNY" -- "MAJZ" -- "DANA" -- "TWRN" -- "HMRN" -- "ECNY" [label ="LD1-25-H03",  penwidth =3 , color="#52d1c8"]
    "ECNY" -- "DANA" -- "ECNY" [label ="LD3-25-H01",  penwidth =3 , color="#498a16"]
    "ECNY" -- "DANA" -- "ECNY" [label ="LD3-25-H02",  penwidth =3 , color="#70f831"]
    "ECNY" -- "2310" -- "5880" -- "5301" -- "2248" -- "ECNY" [label ="JED-10-H17",  penwidth =3 , color="#ebb4e1"]
    "SBCB" -- "ECNY" -- "HMRN" -- "JELS" -- "ROMN" -- "OBHR" -- "SAFA" -- "SBCB" [label ="JED-W40-A01",  penwidth =3 , color="#7ff59c"]
    "SBCB" -- "SAFA" -- "OBHR" -- "HMRN" -- "ECNY" -- "SBCB" [label ="JED-10-H35",  penwidth =3 , color="#e817b9"]
    "2171" -- "ECNY" -- "2171" [label ="JED-10-H19",  penwidth =3 , color="#bf1252"]
    "ABHA" -- "ECNY" -- "DANA" -- "ABHA" [label ="LD3-10-H01",  penwidth =3 , color="#8b60ae"]
    "MAJZ" -- "ECNY" -- "DANA" -- "2510" -- "MAJZ" [label ="LD1-10-H02",  penwidth =3 , color="#1e3c55"]
    "2209" -- "2206" -- "ECNY" -- "2209" [label ="JED-25-H02",  penwidth =3 , color="#1b6092"]
    }

это один из выводов при использовании этих опций (в neato):

graph [bgcolor = ivory2, overlap=false, splines=true, ranksep = "2.75"]

{узел [ширина =1, высота =1, форма = круг, стиль = заполненный, цвет = небесно-голубой] "ECNY" }

край [ len=2, sep=5]

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

также это когда make overlap=scale, но изображение не читается!

перекрытие = масштаб, sep=\"+25,25\", сплайны =true, rankdir=\"TB\"

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

так какие еще атрибуты могут улучшить этот график?

4 ответа

Неизбежно, когда число узлов и ребер увеличивается, мы в конечном итоге останемся без достаточного пространства, чтобы иметь компактный, но тем не менее четкий граф. Тем не менее, я думаю, что есть некоторые вещи, которые мы можем улучшить. В этом случае мы можем воспользоваться тем фактом, что все последовательности ребер образуют петли, которые возвращаются к "ECNY".

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

Во-вторых, я пометил каждую петлю только один раз, причем метка находилась на краю настолько далеко от "ECNY" в петле, насколько я мог получить.

Я сделал эти изменения программно с помощью скрипта Python adjweight.py следующее:

import sys, re, math

for line in sys.stdin:
    line = line.rstrip()
    if re.match(' +"',line):
        loop, attr = line.split(" [")
        loopli = loop.split(" -- ")[1:] 
        # We take all but the first node, to eliminate repeats
        # then we put the list of edges together with "ECNY" first and last.
        i = loopli.index('"ECNY"')
        loopli = loopli[i:] + loopli[:i] + [loopli[i]]
        n = len(loopli)

        # Now we write the multi-edge lines as individual lines so that we can 
        # give each edge an individual weight and length

        for i in range(n-1):
            # We weight edges that are furthest from the center (i.e. those with 
            # numbers closest to n/2) highest and those that are closest to the
            # center are weighted lowest.
            wt = (n/2)/(abs(n/2 - (i+1))+1)
            edgelength = 1/wt
            if i - n//2 + 1 != 0:
                # This edge is the furthest from the center in this loop, so we 
                # label this edge (but not the other edges in the loop)
                attr = ",".join(attr.split(",")[1:])
            # We raise the weights and edge lengths to different powers to adjust
            # the distribution of nodes across the "diameter" of the graph
            print ("    %s -- %s [weight = %f, len = %f, %s" % (
                loopli[i],loopli[i+1],wt**3,edgelength**2,attr))
    else:
        print (line)

... который может быть запущен с python adjweight.py <large.dot >large3.dot, где large.dot это .dot файл показан в вопросе.

Изменение размера шрифта для краев до 10 (по сравнению со значением по умолчанию 14) и запуск large3.dot через neato дал мне следующий график:введите описание изображения здесь

Это распределяет узлы более равномерно по всей странице, и это намного менее загромождается краевыми метками, поэтому мне кажется, что это улучшение. Пограничные метки по-прежнему перекрывают несколько узлов и (особенно в правом верхнем углу графика) другие пограничные метки, потому что overlap Параметр влияет только на узлы и линии ребер, а не на метки ребер.

Изменение относительной длины и веса ребер в зависимости от расстояния от "ECNY" может помочь немного улучшить график.

Мне нужно визуализировать весь путь от определенного узла к другим узлам, поэтому моя проблема с визуализацией узлов не в упрощении.Хорошо, вы уже визуализируете весь путь от определенного узла к другим узлам. Но, как вы сказали, ** результат не читается и содержит перекрытие **. я думаю, что вам нужно, чтобы сделать это визуализирующим, мой следующий совет, чтобы вы попытались визуализировать свой график вручную на небольших данных, используя (3-мерный график), затем закодируйте его или попробуйте найти атрибуты для визуализации его на 3D, если он хорошо работает на малых данные.

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

Почему бы вам сначала не попытаться уменьшить данные на вашем графике (т. Е. Даже если вы получили свою реализацию - трудно следить за графиком), а основная идея представления данных на графике - это упрощение, и вы потеряете его) ПОПРОБУЙТЕ УМЕНЬШИТЬ ДАННЫЕ НА ГРАФЕ.

Я рекомендую использовать программное обеспечение / фреймворк, в котором используются популярные алгоритмы силового макета ( http://en.wikipedia.org/wiki/Force-directed_graph_drawing), наиболее популярными из которых являются Fruchterman-Reingold и Kamada-Kawai. Я использовал R ( http://www.r-project.org/) с пакетом igraph. Я знаю, что это своего рода не ответ на ваш вопрос, поскольку вы сказали, что используете graphvis, но использование силовых алгоритмов - ваш лучший выбор.

Другие вопросы по тегам