2 つの networkx グラフ G と H があるとします。
G=nx.Graph()
fromnodes=[0,1,1,1,1,1,2]
tonodes=[1,2,3,4,5,6,7]
for x,y in zip(fromnodes,tonodes):
G.add_edge(x,y)
H=nx.Graph()
fromnodes=range(2,8)
tonodes=range(8,14)
for x,y in zip(fromnodes,tonodes):
H.add_edge(x,y)
2 つの networkx グラフを結合する最良の方法は何ですか?
ノード名を保存したいと思います (共通ノード 2 ~ 7 に注意してください)。 nx.disjoint_union(G,H) を使用したときは、このようなことは起こりませんでした。
>>> G.nodes()
[0, 1, 2, 3, 4, 5, 6, 7]
>>> H.nodes()
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
>>> Un= nx.disjoint_union(G,H)
>>> Un.nodes()
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
#
H ノードのラベルが変更されました (私が望むものではありません)。同じ番号のノードでグラフを結合したいと考えています。
注意してください。これは、NetworkX で 2 つの重み付けされたグラフを結合するの複製ではありません
3
両方にエッジが存在する場合はどうしますか?翔両刃になるのかな?それとも単一のエッジだけですか?
– ジョエル
2015 年 9 月 18 日 13:47
1
@Joel うーん、両方のケースに興味があります。ただし、シングルエッジとしましょう。
– リー
2015 年 9 月 18 日 13:51
1
シングルエッジケースは、作成したコードによって問題なく処理されます。マルチエッジの場合は U=nx.MultiGraph()
を実行するだけです。
– ジョエル
2015 年 9 月 18 日 13:59
1
例の簡略化: zip(fromnodes,tonodes) の x,y の場合: G.add_edge(x,y) は G.add_edges_from(zip(fromnodes,tonodes)) と書くことができます
– ジョエル
2015 年 9 月 18 日 14:03
------------------------
探している関数for は compose で、両方のグラフに含まれるすべてのエッジとすべてのノードを含むグラフを生成します。両方のグラフに同じ名前のノードがある場合、単一のコピーが新しいグラフに作成されます。両方に同じエッジが存在する場合も同様です。エッジ/ノード属性を含む例を次に示します。
import networkx as nx
G=nx.Graph()
G.add_node(1, weight = 2)
G.add_node(2, weight = 3)
G.add_edge(1,2, flux = 5)
G.add_edge(2,4)
H=nx.Graph()
H.add_node(1, weight = 4)
H.add_edge(1,2, flux = 10)
H.add_edge(1,3)
F = nx.compose(G,H)
#F has all nodes & edges of both graphs, including attributes
#Where the attributes conflict, it uses the attributes of H.
G.nodes(data=True)
> NodeDataView({1: {'weight': 2}, 2: {'weight': 3}, 4: {}})
H.nodes(data=True)
> NodeDataView({1: {'weight': 4}, 2: {}, 3: {}})
F.nodes(data=True)
> NodeDataView({1: {'weight': 4}, 2: {'weight': 3}, 4: {}, 3: {}})
G.edges(data=True)
> EdgeDataView([(1, 2, {'flux': 5}), (2, 4, {})])
H.edges(data=True)
> EdgeDataView([(1, 2, {'flux': 10}), (1, 3, {})])
F.edges(data=True)
EdgeDataView([(1, 2, {'flux': 10}), (1, 3, {}), (2, 4, {})])
これらは属性を保持しますが、競合がある場合は明らかに不可能です。 H の属性が優先されます。
対称的な差分、交差などを行うための他のオプションもあります。
結合する複数のグラフがある場合は、compose_all を使用できます。これは、compose の周囲に for ループをラップするだけです。
4
nx.draw_networkx(G) nx.draw_networkx(H) nx.draw_networkx(F) plt.show() ですべてプロットするときに、すべてのグラフが同じラベルを持つノードの同じ位置を共有するように強制するにはどうすればよいですか?つまり、ノード 1 の座標は 3 つのグラフすべてで同じである必要があります。
– シガー
2017 年 8 月 19 日 0:07
@Sigur プロット コマンドは、nx.draw_networkx(G, pos=pos) のような (オプションの) 入力 pos を受け取ります。 pos は、キーがノード、値がノードの (x,y) 座標である辞書です。自分で定義することも、レイアウト コマンドの一部を使用して定義することもできます。例: pos = nx.spring_layout(F)。
– ジョエル
2017 年 8 月 19 日 4:35
最初にレイアウトを使用して適切な表示を取得し、その後、新しいエッジを追加して別のウィンドウで再度プロットするときに同じ座標を使用したいと考えています。多かれ少なかれ、グラフのタイムラインのようなものを示す一連の図を作成したいと考えています。
– シガー
2017 年 8 月 19 日t 12:38
@Joel - 素晴らしい答えです。ありがとう。これがグラフのグラフで可能かどうか知っていますか?私の場合、ノードの一部は実際にはグラフ オブジェクトであり、それらのグラフには他のノード (さらに多くのグラフが含まれる可能性があります) が含まれています。 compose 関数は最終的にすべてを結合します。これはハッシュ値などに起因すると思います。これを以前に試したことがあるかどうか気になりますか?
– ヤニ
2021 年 7 月 24 日 3:41
------------------------
これでうまくいきました。
U=nx.Graph()
U.add_edges_from(G.edges()+H.edges())
U.add_nodes_from(G.nodes()+H.nodes()) #deals with isolated nodes
または、エッジ属性を保持します:
U.add_edges_from(G.edges(data=True)+H.edges(data=True))
さらに、ノード属性も保持するには:
U.add_nodes_from(G.nodes(data=True)+H.nodes(data=True))
2
NetworkX 2.2 では、追加する前に G.edges() をリストに変換する必要があります。特に MultiGraph が必要な場合。
– トラキシダス ウルフ
2019 年 1 月 31 日 16:33
G のようなグラフがある場合、これはどのように処理しますか: Node1 [label="L1x"]、Node2 [label="L2x"]; H: Node1 [label="L1y"]、Node2 [label="L2x"] ここで、Node 1 は結合グラフ内の個別のノードであることを意味しますが、Node2 は共通です。
– jxramos
2019 年 12 月 20 日 21:50
------------------------
グラフ H を G に追加して G を返す場合は、update メソッドを使用できます。