2017年7月19日水曜日

igraphに取り組み始めた

先日ちょろっと触って放置しているRだが、ここにきてigraphの使い方を学ぶ必要ができたので、igraphを導入としてRに取り組むことになった。
マニュアルをとりあえずさらおうとしたのだがやはり全く頭に入ってこないので、ここに記録を残しておかないといけなさそうという次第。

【R基本】
・<-で代入は入力めんどい
・四則演算は普通
・==、!=、<=
・|で論理和、&で論理積、ふたつ重ねるとベクトルの全要素に対する一つのプール演算
・rm():変数の削除
・特殊変数 ちなみに後続の関数にぶち込むと真偽が返ってくる
  NA: 足すとNAになる 未定義的な? is.na(x)
  NULL: 足すとnumeric(0)になる NAとの使い分けはいまいちわからない is.null(x)
  Inf, -Inf: 無限大 無限大だとis.finite(x)でFalse
  NaN: not a number 0割る0とかやると出てくる is.nan(0/0)==True

【ベクトル】
・c(v1, v2, ,,, ,vn)
・a:b でaからbの数
・rep(a, b): aをb回リピートしたベクトル オプションでtimesつけるとそれをさらに何回、eachをつけるとそれぞれ何回ずつ繰り返す
・seq(a, b, c): aからbまでcおきに
・length(vector): ベクトルの要素数
・dim(vector): ベクトルの次元数
・sum(vector): 合計
・mean(vector): 平均
・sd(vecotor): 標準偏差
・cor(vector1, vector2): 相関係数

【factor】いまいち使いどころがわからず実感わかないので割愛

【行列】
・matrix(a, b, c): b*cの行列 中身はすべてa
・cbind(v1, v2, ,,, , vn): 列ベクトルの連結
・rbind(v1, v2, ,,, , vn): 行ベクトルの連結
・matrix[2,]とかやると2行目、matrix[,2]で2列目
・matrix[1:2, 3:4]で1,2行目の3,4列目
・t(matrix)で転置
・忘れてたけど、配列の先頭indexは1
・行列の要素積は*、内積は%*%とこれまた入力めんどくせえな

【リスト】後日

【データフレーム】
・例
dfr1<-data.frame( ID=1:4,
                           FirstName=c("John", "Jim", "Jane", "Jill"),
                           Female=c(F,F,T,T),
                           Age=c(22,33,44,55)
                          )
・各要素にアクセスするときはdfr1$FirstNameといったように$で結ぶ

【条件分岐等】
for(i in 1:10)
{
    pass
}

while(x<10)
{
    pass
}

if(x==0) y<-0 else y<-y/x


【視覚化】後日

【ネットワーク生成】
・make_empty_graph(n): ノードn個、リンク0のネット(というか群w)
・make_full_graph(n): ノードn個、全結合のネット
・make_star(n): 1つのノードと(n-1)個のノードがリンクをはっているネット
・make_tree(n, children=x, mode='directed'): childrenは生える枝の数なので、真ん中はdegree=x, 末端はdegree=1, 中間はdegree=x+1ということになる。
・make_ring(n): n個のノードで円を作りましょう
・sample_gnm(n=100, m=40): Erdos-Renyi モデルは元はノード数nとリンク生成率pからなるみたいだが、この関数はmでリンクの数を設定する模様
・sample_smallworld(dim=2, size=10, nei=1, p=0.1): 先日作ったことから個人的二おなじみのWSモデル。
・sample_pa(n=100, power=1, m=1, directed=F): Barabasi-Albertpreferential attachment model。スケールフリー奴。
・rewire(net, each_edge(prob=0.1)): netのリンクをある確率で張り替える

【ネットワーク関連】
・library(igraph)でまずはパッケージを読み込みましょう
・net<-graph_from_data_frame(d=links, vertices=nodes, directed=T)の形でネットを作成。2つ(ノードとリンク)のデータフレームを統合してネットワークを形成するのがgraph_from_data_frame()ってことですかね。
・なお本文と順番が前後するが、逆にnetからリンクやノードのデータフレームを取りだすときは、as_data_frame(net, what="edges")でリンク、as_data_frame(net, what="vertices")。
・E(net):リンクの全羅列
・V(net):ノードの全羅列
・E(net)$type:リンクのタイプの羅列
・V(net)&blabla:リンクのblablaの羅列
・ようはgraph_from_data_frame()で統合してできたnetから、リンクとノードの中身にアクセスする方法ですな。
・plot(net, edge.arrow.size=.4, vertex.label=NA)みたいにして可視化
・simplify(net, remove.multiple=F, remove.loops=T)でネットワークの簡素化。remove.multiple=Tで同ノード間の同じ方向の矢印は和をとって一つにしますということ。remove.loops=Tで自分自身へのリンクを削除
・ただしsimplify()を用いると異なるタイプの値でも構わず和をとられてしまう
・as_edgelist(net, names=T): netから隣接リストを取りだす
・as_adjacency_matrix(net, attr="weight"): netから隣接行列を取りだす
・bipartite.projection(net)で2部グラフを形成
・なお2部グラフのリンクは、隣接行列をその転置したものとかけ合わせることで求めることができる

【plotにあたって】
・細かい設定は多すぎるので、これは覚えるものではないと信じていきます
・plot()のレイアウトを設定できる。種類はたくさん。
layout_as_star, layout_components, layout_in_circle, layout_nicely, layout_on_grid, layout_on_sphere, layout_randomly, layout_with_dh, layout_with_drl, layout_with_fr, layout_with_gem, layout_with_graphopt, layout_with_kk, layout_with_lgl, layout_with_mds等(マニュアルに記載のあるものはこれですべて。他にあるかは知らない。)
・力学的モデルに基づいた描画としてFruchterman-Reingoldモデルlayout_with_fr()、Kamad-Kawaiモデルはlayout_with_kk(net)
・par(mfrow=c(2,2), mar=c(0,0,0,0))とかやると、描画ゾーンが4分割される
・dev.off()で分割エンド
・通常plot()ではx=[-1, 1], y=[-1, 1]でrescaleされて表示されるので、自分で大きさを設定するときには、事前に設定したレイアウトlと拡大(縮小)率xを用いてplot(net, rescale=False, layout=l*x)とする


【分析にあたって】
上のようにしたって何も見えてこないので、特徴を見出していかなければならないという話。

・リンクの削除:delete_edges(net, edges)
例えば全てのリンクの重みでは多すぎる場合に平均以下の重みのリンクを消す場合には

cut.off<-mean(links$weight)
net.sp<-delete_edges(net, E(net)[weight<cut.off])

とすれば消せる。他にタイプ別に表示させる際なんかは

net.type1<-net-E(net)[E(net)$type==1]
net.type2<-net-E(net)[E(net)$type==2]

とすることでリンクを削除/分割することできる。また分割前のネットで決めたレイアウトを与えると、分割後のネットがそのレイアウトに従ったまま表示できる。(もはや日本語では何を言っているか自分でもわからない)

l<-layout_with_fr(net) #net1, net2の親玉net
plot(net.1, layout=l) #分割後のnet1のプロットにnetのレイアウトを与える
plot(net.2, layout=l) #分割後のnet2のプロットにnetのレイアウトを与える

【GUIでいじりたい】
tkid<-tkplot(net) でおk
なおレイアウト情報はtkplot.getcoords(tkid)のようにして得られる。得られたレイアウト情報(ここではlとする)はplot(net, layout=l)として指定すればプロットできる。

【グラフの見方はhairball plotのみではない!!】
マニュアルにheatmap(隣接行列の数字を色の濃さにしたマス目みたいなやつ)の表示の仕方が記載されているので参照


【two mode networks】
色変えたりして一つの図に乗っけよう!

【ネットワーク解析】各特徴量の解釈については割愛 Ruminov等参照
・edge_density(net, loops=F)    #リンクの数/(n*(n-1))(directed networkの場合)
・reciprocity(net)    #directed networkにおいて両方向性のリンク
 なお、例えばsample_gnm(n=5, m=10, directed=T)で1つ両方向性のリンクが出た場合には、reciprocity(net)は0.2になる(2/10)
・transitivity(net, type="global")
 全体のtransitivity。type="local"にすると各ノードまわりのtransitivity。(つまりベクトルが返ってくる)
・triad_census(net)
 triangleを形成する全16モチーフごとの数
・diameter(net, directed=F, weights=NA)
 """最長の最短距離"""
 なおネットワークが分断されてる場合には、リンクしている範囲で最長の最短距離
・get_diameter(net, directed=F)
 最長の最短距離の経路 複数個あっても一つしか表示しないっぽい
・degree(net, mode="all")
 各ノードのdegree。modeにはall, in, out, totalの4種があるのだが、allとtotalの違いがいまいちわからない。
・plot(net, vertex.size=degree(net, mode="all")*3)なんてやるとおしゃれになる(degreeが大きいほどノードを大きく表示する)
・degree_distribution(net, cumulative=F, mode="all")
 netの全ノードでの各degreeごとの頻度。cumulative=Tだと累積になる(始点1.0からだんだん下がっていって0.0になる)
 なので、累積のグラフ(正式名称がわからない)が出したいときは

deg_dist<-degree_distribution(net, cumulative=T, mode="all")
plot(x=0:max(degree(net, mode="all")), y=1-deg_dist)

・centr_degree(net, mode="in", normalized=T)
3つの値を返す。graph-level centralityが何かわからなかったけどこちら(http://www.stat.washington.edu/people/pdhoff/courses/567/Notes/l6_centrality.pdf)に書いてありました。式的にはdegreeなどの中心性を表す指標のばらつきが大きいとgraph-level centralityが大きくなるので、"中心"を担うノードがはっきりしているほど大きくなるような値ということでいいのかしら。
$res - 各ノードのdegree
$centralization - sum(max(res)-res)/(theoretical_max)ってところ
$theoretical_max - netと同じノード数で理論上最大のsum(max(res)-res)。netがdirected networkであれば2*(n-1)^2、undirected networkであればn*(n-1)ということでいいのだと思う。

・closeness(net)
各ノードから他全ての(n-1)個のノードへの最短距離の和の逆数
・centr_clo(net)
closeness centralityを求める。
$res - closeness(net)*n
$centralization -
$theoretical_max -

・eigen_centrality(net)
・centr_eigen(net)
・betweenness(net)
・edge_betweenness(net)
・centr_betw(net)       この辺はいったん保留で

・hub_score(net)
・authority_score(net)
Kleinberg's hub centrality scoreというものみたいです。不勉強なのでまだ理解できないのでそれだけ書いておいて次にいきます。

・最短距離の類
mean_distance(net, directed=F): 全2ノード間の最短距離の平均、リンクの逆行あり
mean_distance(net, directed=T): 全2ノード間の最短距離の平均、リンクの逆行なし
distances(net): 全2ノード間の最短距離をn*nの行列で返す
distances(net, weights=NA): 重さ無視
いろいろオプションもある。あるノードから他のノードへの最短距離とかももちろん取り出せる。最短経路を色つけるとかも。そういう時は調べながら書こう、うん。具体例はmanualにいろいろ書いてあるので、必要になったときに自分のタスクでやろうね、うん。

・cocitation(net)
何を求めているかさっぱりわかりません。

・cliques(net)
ネットワークの中で全結合してるサブネットワークを探す関数
・largest_cliques(net)
ネットワークの中で最大のノード数の全結合サブネットワークを返す関数

・クラスタリングの話
いろいろなアルゴリズムがあるのでそれぞれについては今後調べるということでどうか一つ(?)

ceb<-cluster_edge_betweenness(net)
clb<-cluster_label_prop(net)
cfg<-cluster_fast_greedy(net)

出力されるのは「どのように分割するか」という情報であってネットワークではないので、例えば上のように計算した後にcluster_edge_betweennessに基づいてplotする際には以下のようにする。

ceb<-cluster_edge_betweenness(net)
plot(ceb, net)

その他便利グッズ
length(ceb)     #グループ数
membership(ceb)     #各ノードの所属グループ番号
modularity(ceb)
clossing(ceb, net)    #各エッジがinner-group(FALSE)かinter-group(TRUE)か


0 件のコメント:

コメントを投稿