Pythonで共起ネットワークを作成するでは、PythonライブラリのMatplotlibとNetworkXで夏目漱石の『こころ』のテキストをもとに共起ネットワークを作成した。作成したネットワーク図は画像なので、単純に表示して見るだけなのだが、PythonライブラリのPlotlyを使うとインタラクティブな可視化ができる。
今回は、KH CoderでStack OverflowのDeveloper Surveyを可視化するで利用したStack Overflow Annual Developer Surveyのデータを使って、インタラクティブな共起ネットワークを作成する。
Windows10(1903)のWSL(Ubuntu 18.04)とJupyter Notebookを使用。
Plotlyはpipでインストールできる。
他にNetworkXとGraphvizも使う。インストールはPythonで共起ネットワークを作成するを参照。
使用するデータはStack Overflow Annual Developer Surveyで、2019年のデータ(developer_survey_2019.zip)をダウンロードして解凍し、survey_results_public.csvをJupyter Notebookの作業ディレクトリに置いておく。KH CoderでStack OverflowのDeveloper Surveyを可視化すると同じように、過去に経験のあるプログラミング言語やデータベース、フレームワークなどの開発で使われる技術に関する質問の回答結果を使用する。データクリーニングのためのコードを流用するのでsurvey_loader.pyとして保存しておく。以下は使用する質問項目。
それから、「;」区切りの回答を回答者ごとにリストにして、技術ペアごとのJaccard係数を算出する。方法はPythonで共起ネットワークを作成すると同じ関数を使用するので、Gistの全体コードをcoonetwork_sample.pyとして保存しておく。survey_loader.pyとcoonetwork_sample.pyはJupyter Notebookの作業ディレクトリに置いておく。
回答ペアごとのJaccard係数を算出したら、NetworkXとGraphvizでネットワークのノードとエッジの配置を決め、そのデータを使ってPlotlyで可視化する。NetworkXで決めたノードとエッジの配置をもとにPlotlyで可視化する方法がNetwork Graphs in Pythonにあるので、これを参考にした。コードは以下の通り。
Jupyter Notebookでコードを実行すると以下のような共起ネットワーク図が作成された。
さらに、メニューがあってズームなどができるし、マウスオーバーでテキストなどを表示できる。
今回は、KH CoderでStack OverflowのDeveloper Surveyを可視化するで利用したStack Overflow Annual Developer Surveyのデータを使って、インタラクティブな共起ネットワークを作成する。
環境
Windows10(1903)のWSL(Ubuntu 18.04)とJupyter Notebookを使用。
必要ライブラリなどのインストール
Plotlyはpipでインストールできる。
他にNetworkXとGraphvizも使う。インストールはPythonで共起ネットワークを作成するを参照。
データのクリーニングとJaccard係数の算出
使用するデータはStack Overflow Annual Developer Surveyで、2019年のデータ(developer_survey_2019.zip)をダウンロードして解凍し、survey_results_public.csvをJupyter Notebookの作業ディレクトリに置いておく。KH CoderでStack OverflowのDeveloper Surveyを可視化すると同じように、過去に経験のあるプログラミング言語やデータベース、フレームワークなどの開発で使われる技術に関する質問の回答結果を使用する。データクリーニングのためのコードを流用するのでsurvey_loader.pyとして保存しておく。以下は使用する質問項目。
- LanguageWorkedWith(プログラミング言語、スクリプト、マークアップ言語)
- DatabaseWorkedWith(データベース)
- PlatformWorkedWith(プラットフォーム)
- WebFrameWorkedWith(ウェブフレームワーク)
- MiscTechWorkedWith(その他の技術)
- DevEnviron(開発環境)
それから、「;」区切りの回答を回答者ごとにリストにして、技術ペアごとのJaccard係数を算出する。方法はPythonで共起ネットワークを作成すると同じ関数を使用するので、Gistの全体コードをcoonetwork_sample.pyとして保存しておく。survey_loader.pyとcoonetwork_sample.pyはJupyter Notebookの作業ディレクトリに置いておく。
ネットワーク図の作成
回答ペアごとのJaccard係数を算出したら、NetworkXとGraphvizでネットワークのノードとエッジの配置を決め、そのデータを使ってPlotlyで可視化する。NetworkXで決めたノードとエッジの配置をもとにPlotlyで可視化する方法がNetwork Graphs in Pythonにあるので、これを参考にした。コードは以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | import os import numpy as np import pandas as pd import networkx as nx from networkx.drawing import nx_agraph from plotly import graph_objs as go # Stack Overflow Annual Developer Surveyのデータをクリーニングする関数をインポート from survey_loader import to_df, clean_df # Jaccard係数を算出する関数をインポート from coonetwork_sample import bform2pair, pair2jaccard def build_interactive_network(G, pos, pr_values): # Plotlyで共起ネットワークを可視化 # nodeの大きさと色をページランクアルゴリズムによる重要度(pr_values)により変える # edgeデータの作成 edge_x = [] edge_y = [] for edge in G.edges(): x0, y0 = pos[edge[ 0 ]] x1, y1 = pos[edge[ 1 ]] edge_x.append(x0) edge_x.append(x1) edge_x.append( None ) edge_y.append(y0) edge_y.append(y1) edge_y.append( None ) edge_trace = go.Scatter( x = edge_x, y = edge_y, line = dict (width = 0.5 , color = '#888' ), hoverinfo = 'none' , mode = 'lines' ) # nodeデータの作成 node_x = [] node_y = [] for node in G.nodes(): x, y = pos[node] node_x.append(x) node_y.append(y) node_trace = go.Scatter( x = node_x, y = node_y, text = list (G.nodes()), textposition = 'top center' , mode = 'markers+text' , hoverinfo = 'text' , marker = dict ( showscale = True , # colorscale options #'Greys' | 'YlGnBu' | 'Greens' | 'YlOrRd' | 'Bluered' | 'RdBu' | #'Reds' | 'Blues' | 'Picnic' | 'Rainbow' | 'Portland' | 'Jet' | #'Hot' | 'Blackbody' | 'Earth' | 'Electric' | 'Viridis' | colorscale = 'Rainbow' , reversescale = False , color = [], size = 10 , colorbar = dict ( thickness = 15 , title = 'Page Ranking' , xanchor = 'left' , titleside = 'right' ), line_width = 2 )) # nodeの色、サイズ、マウスオーバーしたときに表示するテキストの設定 node_adjacencies = [] node_text = [] for node, adjacencies in enumerate (G.adjacency()): # nodeに接続するedgeの数 node_adjacencies.append( len (adjacencies[ 1 ])) node_text.append( '{} connection(s)' . format ( len (adjacencies[ 1 ]))) node_trace.marker.color = pr_values node_trace.marker.size = [value * 1000 for value in pr_values] node_trace.hovertext = node_text # ネットワーク図の可視化 fig = go.Figure(data = [edge_trace, node_trace], layout = go.Layout( showlegend = False , hovermode = 'closest' , margin = dict (b = 20 ,l = 5 ,r = 5 ,t = 40 ), xaxis = dict (showgrid = False , zeroline = False , showticklabels = False ), yaxis = dict (showgrid = False , zeroline = False , showticklabels = False )) ) fig.show() def build_network(jaccard_dict): # 回答ペアごとのJaccard係数をもとにnodeとedgeのレイアウトを決めてネットワーク図を可視化 G = nx.Graph() # 接点/単語(node)の追加 # ソートしないとネットワーク図の配置が実行ごとに変わる nodes = sorted ( set ([j for pair in jaccard_dict.keys() for j in pair])) G.add_nodes_from(nodes) print ( 'Number of nodes=' , G.number_of_nodes()) # 線(edge)の追加 for pair, coef in jaccard_dict.items(): G.add_edge(pair[ 0 ], pair[ 1 ], weight = coef) print ( 'Number of edges=' , G.number_of_edges()) # nodeの配置方法の指定 seed = 0 np.random.seed(seed) # k = node間反発係数 #pos = nx.spring_layout(G, k=0.3, seed=seed) # できるだけnodeが重ならないようにする(Graphvizを使う) pos = nx_agraph.graphviz_layout( G, prog = 'neato' , args = '-Goverlap="scalexy" -Gsep="+6" -Gnodesep=0.8 -Gsplines="polyline" -GpackMode="graph" -Gstart={}' . format (seed)) # ページランクアルゴリズムによる重要度 pr = nx.pagerank(G) # 共起ネットワークの可視化 build_interactive_network(G, pos, list (pr.values())) def main(): df = to_df() df = clean_df(df) df[ 'tech' ] = df[df.columns[ 1 :]]. apply ( lambda row: ';' .join(row).split( ';' ), axis = 1 ) print (df[ 'tech' ].head()) # Jaccard係数の計算 pair_count = bform2pair(df[ 'tech' ].tolist(), min_cnt = 20 ) jaccard_dict = pair2jaccard(pair_count, df[ 'tech' ].tolist(), edge_th = 0.4 ) # 共起ネットワーク作成 build_network(jaccard_dict) if __name__ = = '__main__' : main() |
結果
Jupyter Notebookでコードを実行すると以下のような共起ネットワーク図が作成された。

さらに、メニューがあってズームなどができるし、マウスオーバーでテキストなどを表示できる。


0 件のコメント:
コメントを投稿