#はじめに
最近何度も何度も共起ネットワーク図を作る場面があり、前の記事などで、なんやかんややっていたけれど、とりあえず共起関係をサクッと作る関数を作っておくことにした。
@hiro429 さんに助力いただいて、重複削除が解消できました!ありがとうございます
#関数本体
dataframe:処理対象の列が含まれるpd.dataframe
colname:共起ネットワーク図を作りたい項目(列名)
sep:区切り
#!pip install pyvis
def make_co_occur_df(dataframe,colname,sep):
df_co_occur_network = \
pd.merge(dataframe[colname].str.split(sep,expand=True).stack().reset_index(),
dataframe[colname].str.split(sep,expand=True).stack().reset_index(),
on="level_0",how="outer")\
.pipe(lambda df: df[df["0_x"] != df["0_y"]])\
.groupby(["0_x","0_y"],as_index=False).size()\
.reset_index()\
.rename(columns={"0_x":"source","0_y":"target",0:"weight"})\
.pipe(lambda df:df[pd.DataFrame(np.sort(df[['source','target']].values)).duplicated()])
#20210408最終行追加
#source,target,weight(共起回数)のdfを返す。
return df_co_occur_network
少し工夫した点は、共起ネットワークでいうセルフループを消す処理↓。
.pipe(lambda df: df[df["0_x"] != df["0_y"]])\
- 20200809 sourceとtargetを入れ替えると二重に出力されているのを発見。要修正
- 20210408追加 @hiro429 さんに助力いただいて、重複削除が解消できました!ありがとうございます
#使い方
####データ読みこみ(dataframeに読み込み)
import pandas as pd
df=pd.read_csv("https://storage.googleapis.com/yoshino/yoshino.csv",encoding='cp932')
df.head()
####今回作成対象の列のIPCは|で区切られていることを確認。
#IPC列を処理
colname="IPC"
sep="|" #sepはここに反映させる。
edges=make_co_occur_df(df,colname,sep)
# networkxで読み込み。必要に応じてcoefなど出す。
import networkx as nx
G = nx.from_pandas_edgelist(edges, edge_attr=True)
####pyvisでhtmlを出力する。可視化の際の出力設定などは公式参照
!pip install pyvis
from pyvis.network import Network
pyvis_G = Network(height='600px', width='800px')
pyvis_G.from_nx(G)
pyvis_G.force_atlas_2based()
pyvis_G.show_buttons()
#pyvis_G.set_options("physics")
pyvis_G.show("mygraph.html")
####mygraph.htmlを開く。
#その他
html画面で、表示を色々弄った後に
下の方の「generate option」を押せば、今後のoption設定で使える(と思われる)設定が出る。
options
また、
pyvis_G = Network(height='600px', width='800px',notebook=True)
とするとnotebook内に表示されるようだが、colaboratoryではエラーが出て見れなかった。
- ネットワーク図が動くのが嫌な場合、操作パネルの下の方にあるphysicsのうち、enabledのチェックを外せばいい。
20220530更新
データ量が多いと上の関数だとクラッシュしがちだったので、違うアプローチを検討。
itertoolsで組み合わせ抽出してからdataframeに投入
こちらの方がいいかも
import itertools
def get_combi(lis):
pairlist = []
for pair in itertools.combinations(lis, 2):
pairlist.append(pair)
return pairlist
from itertools import chain
def make_co_occur_df2(dataframe,colname,sep):
nested_tuple = dataframe[colname].astype(str).apply(lambda x:x.split(sep)).apply(get_combi)
tuplelists = nested_tuple.tolist()
my_unnested_list = list(chain(*tuplelists))
edges = pd.DataFrame(my_unnested_list).groupby([0,1],as_index=False).size()\
.pipe(lambda df:df[df[0]!=df[1]])\
.sort_values(by=["size"],ascending=False)\
.rename(columns={0:"source",1:"target"})
return edges