web-dev-qa-db-ja.com

Networkx:複数のツリーを一度にプロットするために複数のルートを指定する方法は?

Networkxには、放射状レイアウト(graphvizの「twopi」)を使用してツリーをプロットする関数があります。

import pydot
from networkx.drawing.nx_pydot import graphviz_layout

pos = graphviz_layout(G, prog='twopi', root=root, args='')

引数rootを使用してルートノードを指定できます(これはargs += f" -Groot={root}"として内部でargsに追加されます)。

しかし、グラフが複数の切断されたコンポーネントで構成されている場合、複数のルートをどのように指定しますか?つまり木の森。

ルートパラメータを指定せずに次のプロットを取得します。

enter image description here

視覚的にわかるように、10本の木の真のルートノードを正しく選択していますが、12本では、真のルートノードのchildを中心として選択しています(そしてしたがって、一部のブランチは、他のブランチと比較して、実際よりも浅く見えます)。

複数のツリーのルートを手動で指定するにはどうすればよいですか?

6
brazofuerte

Graphvizのtwopiレイアウトの単一のグラフでこれを行う方法はないと思います。 Twopishouldは、一般的に、各サブグラフのルートノードを設定するのに適しています。これは、 docsで説明されているためです リーフノードから最も遠いノードの1つをランダムにルートとして選択するため、単一のルートノードがある場合、これは予想されるトポロジー配置につながるはずです。それが当てはまらず、各サブグラフの根を手動で設定したい場合でも、私がこれに取り組む方法は、グラフは、コンポーネントのサブグラフを接続し、各コンポーネントをサブプロットグラフの個別の軸にプロットして、それぞれにカスタムの graphviz_layout を作成します。

これは、次のサンプルグラフを使用してこれを行う方法です。

from matplotlib import pyplot as plt
import pygraphviz
from networkx.drawing.nx_agraph import graphviz_layout

result_set = {('plant','tree'), ('tree','Oak'), ('flower', 'rose'), ('flower','daisy'), ('plant','flower'), ('tree','pine'), ('plant','roots'), ('animal','fish'),('animal','bird'), ('bird','robin'), ('bird','falcon'), ('animal', 'homo'),('homo','homo-sapiens'), ('animal','reptile'), ('reptile','snake'),('fungi','mushroom'), ('fungi','mold'), ('fungi','toadstool'),('reptile','crocodile'), ('mushroom','Portabello'), ('mushroom','Shiitake'),('pine','roig'),('pine','pinyer'), ('tree','eucaliptus'),('rose','Floribunda'),('rose','grandiflora')}
G=nx.from_edgelist(result_set, create_using=nx.DiGraph)

既存のサブグラフを反復処理するには、現在のグラフのコピーが無向グラフでない場合は無向グラフとして作成し、 nx.connected_component_subgraphsを使用してサブグラフのリストを作成する必要があります

UG = G.to_undirected()
subgraphs = list(nx.connected_component_subgraphs(UG))

さまざまなコンポーネントのルートノードをノード'plant''animal'、および'mushroom'にしたいとしているとしましょう。サブプロットのセットを作成し、それぞれを繰り返します。軸、サブグラフオブジェクト、およびルートのリスト(それらが同じ順序になっていることを確認)とともに、対応するルートノードを設定する各サブグラフの新しいレイアウトを作成します。

n_cols = 2
roots = ['plant','animal','mushroom']
fig, axes = plt.subplots(nrows=int(np.ceil(len(subgraphs)/n_cols)), 
                         ncols=n_cols, 
                         figsize=(15,10))
plt.box(False)

for subgraph, root, ax in Zip(subgraphs, roots, axes.flatten()):
    pos = graphviz_layout(G,  prog='twopi', args=f"-Groot={root}")
    nx.draw(subgraph, pos=pos, with_labels=True, 
            node_color='lightblue', node_size=500, ax=ax)


enter image description here

3
yatu