質問: 日本のイベントをまとめたデータフレーム【df_event】があります。 ・df_event["協賛会社"] ・df_event["企画会社"] ・df_event["運営会社"] のデータを一つのイベントで2つや3つある会社をnetworkxでグラフ化したいと思っています。 (【イメージ画像】のようにどの会社同士の繋がりが強いかを可視化したいです。) networkxに初めて挑戦するのでヒントだけでもいただけたらと思います。 どなたかお力添えをよろしくお願いいたします。。 【df_event】 | イベント名 | 都道府県名 | 開催 | 協賛会社 | 企画会社 | 運営会社 | | --- | --- | --- | --- | --- | --- | | 〇〇祭り | 北海道 | 1989 | F社 | A社、D社 | G社 | | □□大会 | 北海道 | 1975 | A社、H社 | B社 | H社 | | ・ | ・ | ・ | ・ | ・ | | | △△パーティー | 東京都 | 2013 | A社 | C社、D社 | B社、F社 | | ●●祭 | 神奈川県 | 1982 | B社 | E社、F社、A社 | G社 | | ・ | ・ | ・ | ・ | ・ | | | ✖︎✖︎生誕祭 | 大阪府 | 1969 | F社 | G社、B社 | A社 | | ■■ディナーショー | 大阪府 | 2004 | A社、G社 | C社 | A社、C社、H社 | | ・ | ・ | ・ | ・ | ・ | ・ | | ▲▲イベント | 沖縄 | 1997 | B社 | D社、E社、F社 | H社 | 【イメージ画像】 ![イメージ説明](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/f130e29df825b2d35ecb45e512e7b0c8.png)
回答: ``` イベント名 都道府県名 開催 協賛会社 企画会社 運営会社 〇〇祭り 北海道 1989 F社 A社、D社 G社 ``` となっていた場合、F社、A社、D社、G社 が関係があるとし、その中の2つの組み合わせに対して辺を追加する形でグラフを作成しました。(itertools.combinations を使用) ``` G社 A社 G社 F社 G社 D社 A社 F社 A社 D社 F社 D社 ``` 関係の強さを表すために penwidth 属性に回数を記録し、すでに辺が存在する場合は +1 するようにしました。(penwidth 属性は Graphviz で辺を描画する際の太さに利用されます) 必要なライブラリについて netoworkx 自体はグラフの可視化機能は提供しておらず、matplotlib または Graphviz を使って行うので、今回は Graphviz を使いました。 可視化には別途、`pydot` という Python のライブラリと `graphviz` というソフトウェアが必要になります。 Linux では apt でインストールできますが、それ以外の環境の場合は OS にあったバージョンのバイナリを公式サイトからダウンロードしてください。 Download pydot は `pip install pydot` でインストールできます。 Linux の場合のコマンド ``` pip install pydot networkx # Graphviz と日本語フォントをインストール apt install -y graphviz fonts-ipafont fc-cache -fv ``` コード ``` from io import StringIO from itertools import combinations import networkx as nx import pandas as pd from IPython.display import Image, display data = StringIO( """ イベント名,都道府県名,開催,協賛会社,企画会社,運営会社 〇〇祭り,北海道,1989,F社,A社、D社,G社 □□大会,北海道,1975,A社、H社,B社,H社 △△パーティー,東京都,2013,A社,C社、D社,B社、F社 ●●祭,神奈川県,1982,B社,E社、F社、A社,G社 ✖︎✖︎生誕祭,大阪府,1969,F社,G社、B社,A社 ■■ディナーショー,大阪府,2004,A社、G社,C社,A社、C社、H社 ▲▲イベント,沖縄,1997,B社,D社、E社、F社,H社 """ ) def splitter(text): """句読点区切りの値をリストにする。 例: "A社、D社" -> "A社", "D社"] """ return [x.strip() for x in text.split("、")] df = pd.read_csv( data, converters={"協賛会社": splitter, "企画会社": splitter, "運営会社": splitter} ) display(df) # 会社は全部ひとまとめにする。 df["会社"] = df["協賛会社"] + df["企画会社"] + df["運営会社"] # 重複は消す。 df["会社"] = df["会社"].apply(lambda x: set(x)) # 会社の関係をグラフにする。 G = nx.Graph(fontname="IPAGothic") # 日本語フォントを設定する # 環境に応じて、ここは変えてください。Windows なら例えば「メイリオ」とか for row in df.itertuples(): # 各イベントごとに、関係している会社の組み合わせを辺として追加する。 for u, v in combinations(getattr(row, "会社"), 2): if G.has_edge(u, v): # すでに辺が存在する場合は penwidth の値を +1 する。 G.edges[u, v]["penwidth"] += 1 else: # 辺がまだ存在しない場合は辺を追加する。 G.add_edge(u, v, penwidth=1) def show_graph(G): D = nx.nx_pydot.to_pydot(G) D.write_png("temp.png", prog="dot") display(Image("temp.png")) show_graph(G) ``` ![イメージ説明