1 パッケージ読み込み


library(igraph); library(igraphdata)

2 グラフ作成.


2.1 エッジリストからグラフオブジェクト生成.

  • エッジリストをvectorで与える.
    • make_graph ベクトルからグラフ生成.
    • ノードラベルを名に値がわりふられるV(g)$name
  • エッジリストをmatrixで与える.
    • graph_from_edgelist(), graph.edgelist()
  • エッジリストをdata.frameで与える.
    • graph_from_data_frame()
  • 有向, 無向グラフ
    • 無向グラフの場合, 上の関数の引数でdirected =F. デフォルトはT
    • make_directed_graph, make_undirected_graph
  • 自己ループと多重ループの削除 simplify
# エッジリストをベクトルで与える.   
v1 <- c("1","2", "1","3", "1","4", "2","3", "3","3","4","2", "2","4")
v2 <- c(1, 2, 1, 3, 1, 4, 2, 3, 3, 3, 4, 2, 2, 4) 

# エッジリストをマトリックスもしくはデータフレームで与える. 
m1 <- matrix(c("A","B", "A","C", "A","D", "B","C", "C","C", "D","B","B","D"), 
             byrow = T, ncol = 2) 
m2 <- matrix(c(1,2, 1,3, 1,4, 2,3, 3,3, 4,2, 2,4), 
             byrow = T, ncol = 2)
d1 <- data.frame(m1, stringsAsFactors = F)


make_graph(v1, directed = F)
make_graph(v2, directed = F)

graph_from_edgelist(m1, directed = F)
graph.edgelist(m2, directed = F)
graph_from_data_frame(d1, directed = F)
## IGRAPH 6808619 UN-- 4 7 -- 
## + attr: name (v/c)
## + edges from 6808619 (vertex names):
## [1] 1--2 1--3 1--4 2--3 3--3 2--4 2--4
## IGRAPH 97801d5 U--- 4 7 -- 
## + edges from 97801d5:
## [1] 1--2 1--3 1--4 2--3 3--3 2--4 2--4
## IGRAPH 9b0de2d UN-- 4 7 -- 
## + attr: name (v/c)
## + edges from 9b0de2d (vertex names):
## [1] A--B A--C A--D B--C C--C B--D B--D
## IGRAPH baf436a U--- 4 7 -- 
## + edges from baf436a:
## [1] 1--2 1--3 1--4 2--3 3--3 2--4 2--4
## IGRAPH 5f8293b UN-- 4 7 -- 
## + attr: name (v/c)
## + edges from 5f8293b (vertex names):
## [1] A--B A--C A--D B--C C--C B--D B--D

2.2 ノード・エッジを直接記述する.

  • graph_from_literal
  • make_graph(~) リテラルの前に~を書く
  • 有向グラフの場合 x-+y のように書く, -の数は無視される x----y
par(mfrow = c(1,3))
plot(graph_from_literal( A-B-C-A, D-C-E, C-G, H ), main = "graph_from_literal")
plot(graph_from_literal( A-+B, B+-C, D-+E-+F, G+-+H, I), main = "graph_from_literal")
plot(make_graph( ~ A-+B, B+-C, D-+E-+F, G+-+H, I), main = "make_graph( ~ )")

2.3 隣接行列からグラフオブジェクトの生成.

  • graph_from_adjacency_matrix,graph.adjacency有向グラフの場合, 上三角行列の情報が使われる.
  • diag = Fで自己ループを除外
  • 正方行列でないとエラー
# 隣接行列の作成
set.seed(1) 
adjm <- matrix(sample(x = 0:1, size = 100, replace = TRUE, prob = c(0.8,0.2)), ncol = 10)

# 隣接行列からグラフオブジェクト作成 
g <- graph_from_adjacency_matrix(adjmatrix = adjm, mode = "undirected", diag = F )

# グラフ描画  
plot(g)

2.4 相関係数行列からグラフの作成.

  • 2値データに変換して重みなしグラフを生成
  • 相関係数を重みとする
# 相関係数行列を -> 2値データに変換 -> 無向グラフ 
thresh <- 0.7
g1 <- cor(mtcars) %>% 
  {ifelse(. < thresh, 0, 1)} %>% 
  graph_from_adjacency_matrix(., mode = "undirected", diag = F)

# 相関係数行列(spearman) -> 重み付き無向グラフ
g2 <- cor(mtcars, method = "spearman") %>%
  graph_from_adjacency_matrix(., mode = "undirected", weighted = T, diag = F)

# 重みをエッジの幅に反映させる.  相関の正負をエッジの色に反映させる 
ewid <- abs(igraph::E(g2)$weight)*2
ecol <- ifelse(igraph::E(g2)$weight < 0 , "steelblue3", "red")

# グラフ描画
par(mfrow = c(1,2), mar = c(0,0,0,0))
plot(g1, layout = layout_nicely,
     vertex.label.cex = 0.8,
     vertex.frame.color = "white", 
     vertex.size = 10, 
     vertex.color = "lightblue")

plot(g2, layout = layout_in_circle, 
     vertex.label.cex = 0.8,
     vertex.frame.color = "white", 
     vertex.size = 10, 
     vertex.color = "lightblue",
     edge.width = ewid,
     edge.color = ecol)

2.5 make_graphでグラフ名を与えると作られるグラフ.

  • make_graphの引数に以下のグラフ名(26ある)を入れると作られる
  • 他の引数は無視される.
gs <- c("Bull","Chvatal","Coxeter","Cubical","Diamond","Folkman",
        "Franklin","Frucht","Grotzsch","Heawood","Herschel",
        "House","HouseX","Levi","McGee","Meredith",
        "Noperfectmatching","Nonline","Petersen","Robertson","Smallestcyclicgroup",
        "Thomassen","Tutte","Uniquely3colorable","Walther","Zachary")

par(mfrow = c(3,3), mar = c(1,0,1,0))
invisible(lapply(seq_along(gs), function(i){
  plot(make_graph(gs[i]), vertex.label = NA, main = gs[i])
  }))

2.6 特殊なグラフ.

  • make_tree 木, make_star 星, make_ring リング, make_lattice格子
  • 引数としてノード数, 有向, 無向などを指定する
  • make_bipartite_graph 二部グラフ, make_chordal_ring, make_de_bruijn_graphドブリングラフ make_ego_graph, make_empty_graph エッジ無しのグラフ, make_full_graph 完全グラフ, make_full_citation_graph 完全引用グラフ,
  • graph_from_atlas「An Atlas of Graphs」にある、7つの頂点を持つすべての無向グラフ(0~1252).
par(mar = c(1,0,1,0), mfrow = c(3,3)) 
plot(make_tree(5), main = "make_tree")                
plot(make_star(5), main = "make_star")                       
plot(make_ring(10), main = "make_ring")                        
plot(make_lattice(c(3,3)), main = "make_lattice") 
plot(make_full_citation_graph(10, directed = F), main = "make_full_citation_graph") 
plot(make_bipartite_graph(rep(0:1, length = 10), c(1:10)), main = "make_bipartite_graph")
plot(graph_from_atlas(100), main = "graph_from_atlas(100)") 

2.7 スケールフリーグラフ, ランダムグラフ.

  • sample_pa, barabasi.game スケールフリーグラフ. ノード数とエッジ数
  • make_full_graph, graph.full 完全グラフ. ノード数を指定する.
  • sample_gnp, sample_gnm,erdos.renyi.game,random.graph.game ランダムグラフ. すべての可能なエッジが一定確率で作成. 確率もしくはエッジ数を指定する. G(n, p), G(n, m)
par(mar = c(0,0,1,0), mfrow = c(1,3))

# スケールフリーグラフ 
plot(sample_pa(n = 20, power = 1, directed = F), main = "'sample_pa' scale free graph")

# 完全グラフ
plot(make_full_graph(20), main = "'make_full_graph' complete graph")

# ランダムグラフ(ノード50個、p = 0.1)
plot(sample_gnp(n = 20, p = 0.1, direct = F), main = "'sample_gnp' random graph p = 0.1")

3 グラフファイル読み込み・書き出し.


3.1 gml形式のファイル読み込み.

  • read_graph(file, format), read.graph(file, format)
  • グラフフォーマット“pajek”, “ncol”, “lgl”, “graphml”, “dimacs”, “graphdb”, “gml”, “dl”
# gml形式の読み込み 
g <- read_graph("~/pub/sampledata/dataset/network/gml/lesmis.gml", format = "gml") 
 
# ノードラベル  
V(g)$label %>% head 

# weight
E(g)$value %>% head 

# 書き出し
write_graph(graph = g, file = "./graph.txt", format = "edgelist")
 

4 igraphのネットワークデータセット(igraphdataパッケージ).


Koenigsberg  Koenigsbergの橋 G(4, 7)
UKfaculty  英国の大学教員のネットワーク G(4, 817)
USairports  米国の空港ネットワーク、2010年12月 G(81, 23473)
enron  エンロン(米)の電子メールネットワーク G(184, 125409)
foodwebs  フードウェブのコレクション G(1316, 6300)
immuno  免疫グロブリン相互作用ネットワーク G(1316, 6300)
karate  Zacharyの空手クラブネットワーク G(34, 78)
kite  クラックハートの凧  G(10, 18)
macaque  視覚の脳の領域と接続 G(45, 463)
rfid  病院遭遇ネットワーク G(75, 32424)
yeast  酵母タンパク質相互作用ネットワーク G(2617, 11855)
 
library(igraphdata) 
data(package = "igraphdata") 
data(package = "igraphdata", list = "Koenigsberg")
plot(Koenigsberg)

5 グラフ描画.


5.1 グラフ描画.

  • ?plot.igraph, ?igraph.plotting で詳細なhelpを見る.
# グラフ
set.seed(1) 
g <- random.graph.game(n = 20, p = 0.1, directed = F) %>%
  set_vertex_attr(., name = "label", value = LETTERS[1:vcount(.)]) %>% 
  set_edge_attr(., name = "label", value = 1:ecount(.)) 
 

# 描画
par(mar = c(0,0,1,0))
plot(g, 
     layout = layout_with_fr,
     vertex.color = "navy", # sort(unique(degree(g)))[factor(degree(g))] + 1,
     vertex.frame.color = "white", 
     vertex.label = V(g)$label,
     vertex.label.color = "white",
     vertex.label.cex = 1,
     vertex.label.dist = 0,
     vertex.label.family = "Helvetica",
     vertex.label.font = 2,  # 1:plane, 2:bold, 3:italic, 4:bolditalic, 5:symbol
     vertex.size = (degree(g) + 5)*2, # 次数を反映させる
     vertex.size2 = 10, # shapeでrectangleを選んだ場合の高さ
     vertex.shape = "rectangle", # circle,square,csquare,rectangle,crectangle,vrectangle,none
     edge.color = "grey",
     edge.width = 2,
     edge.arrow.size = 0.1,
     edge.arrow.width = 3, # 1:solid, 2:dashed, 3:dotted, 4:dotdash, 5:longdash, 6:twodash.
     edge.label.cex = 0.8,
     edge.label.color = "red",
     edge.label.family = "Helvetica",
     edge.label.font = 2,
     edge.lty = 2,
     main = "layout_with_fr"
     )

5.2 コミュニティーごとに色分け.

# コミュニティー検出
cl.lv <- cluster_louvain(g) 

# コミュニティーごとのノードの色、次数が0のノードは同色 
v.c <- RColorBrewer::brewer.pal(n = max(cl.lv$membership), name = "Set2")[cl.lv$membership] %>% 
  ifelse(degree(g) == 0, "grey", .)

# 描画
plot(g, vertex.color = v.c) 

5.3 サークルレイアウトで次数の大きい順に配置layout_in_circle(g, order).

  • ノードの配置をorderで変える
lay.crc <- layout_in_circle(g, order = order(degree(g), decreasing = T))
plot(g, layout = lay.crc)

5.4 色々なレイアウト関数. layout_*

# グラフレイアウト関数
lays <- grep("^layout_.+", 
             unclass(utils::lsf.str(envir = asNamespace("igraph"), all = T)), value = T)

# 全部のlayout関数を試す.
par(mfrow = c(3,3))
suppressWarnings(
  for (x in lays) {
    possibleError <- tryCatch({
      coords <- do.call(x, list(g))
      par(mar = c(0,0,1,0))
      plot(g, layout = coords,
           vertex.label = V(g)$name, 
           vertex.label.color = "black",
           vertex.frame.color = "white",
           vertex.label.cex = 1, 
           vertex.size = 15, 
           vertex.color = "lightblue",
           vertex.label.family = "Helvetica", 
           vertex.shape = "circle",
           edge.label = NA,
           edge.color = "gray80", 
           edge.width = 1, 
           edge.lty = 1,
           main = x)
      },
      error = function(e) {
        print(paste("Error in layout ",x,sep = ""))
      })
    if (inherits(possibleError, "error")) next
    }
  )

## [1] "Error in layout layout_as_bipartite"
## [1] "Error in layout layout_modifier"
## [1] "Error in layout layout_spec"
## [1] "Error in layout layout_with_sugiyama"

6 グラフオブジェクトの操作.


6.1 ノード数, エッジ数, 連結成分.

  • ノード数, エッジ数, 次数vcount, ecount, degree
  • ノードラベル V(g)$name
  • 隣接ノード adjacent_vertices, V(g)[nei(1)], neighbors(g, 1)
  • エッジの重み(weight = Tにした場合) E(g)$weight
  • エッジのid get.edge.ids
# グラフ
g <- graph.atlas(100);  V(g)$name <- LETTERS[1:6] 
 
# ノード数、エッジ数, 次数, 隣接ノード
V(g); E(g) # ノード, エッジ
vcount(g); ecount(g) # ノード数, エッジ数 
degree(g) # ノードごとの次数(各頂点が連結している辺の数)
adjacent_vertices(g, 1); V(g)[nei(1)]; neighbors(g, 1) # 隣接ノード

6.2 エッジリスト, 隣接リスト, 隣接行列 取り出し.

  • エッジリスト(matrix) as_edgelist, get.edgelist,
  • エッジリスト(data.frame) as_data_frame, get.data.frame. dplyr::as_data_frameと区別する. エッジの属性値も出してくれる. what ="vertices"にすればノード属性値のデータフレームを返す. what ="both"では両方
  • 隣接リストas_adj_list,get.adjlist
  • 隣接行列 as_adjacency_matrix, get.adjacency
as_edgelist(g) # エッジリスト(matrix)
igraph::as_data_frame(g) # エッジリスト(data.frame)
igraph::as_data_frame(g, what = "both")
as_adj_list(g) # 隣接リスト(頂点同士の隣接関係を確認する)
as_adjacency_matrix(g)[1:6,1:6] # 隣接行列

6.3 ノード, エッジの追加・削除.

  • disjoint, %du% 2つ以上のグラフを結合(union)する.
  • add_vertices, add.vertices ノードの追加
  • add_edges, add.edges エッジの追加
  • delete_vertices, delete.vertices ノード削除. 非連結成分を削除する場合 delete_vertices(g, V(g)$name[degree(g)==0])
  • delete_edges エッジの削除(エッジのidで指定)
# 3つの完全グラフの和集合 
g <- disjoint_union(make_full_graph(4), make_full_graph(4), make_full_graph(4))

#ノードの追加  
g1 <- add_vertices(graph = g, nv = 3) 

# エッジの追加(ノード1,6間, 1,11間, 6,11間にエッジを追加する) 
g2 <- add_edges(g1, c(1,6, 1,11, 6,11, 4,13, 8,14))  

# エッジの削除 (エッジのidで指定する)
g3 <- delete_edges(g2, get.edge.ids(g, c(2,4, 6,7, 9,12 )))

# 非連結成分の削除
g4 <- delete_vertices(g3, V(g3)[degree(g3) == 0])

# 非連結成分の削除, 連結成分ごとに分割,
gcs <- delete_vertices(g1, V(g1)[degree(g1) == 0]) %>% decompose()


# グラフ描画 
par(mfrow = c(2,3), c(0,0,1,0))
plot(g)  
plot(g1, main = "add_vertices")
plot(g2, main = "add_edges")
plot(g3, main = "delete_edges")
plot(g4, main = "delete_vertices")

# 連結成分ごとに描画
par(mfrow = c(1,3), mar = c(0,0,1,0))

invisible(lapply(gcs, function(x)plot(x)))

6.4 ノード, エッジの属性値を追加.

  • 属性値の名前は自由につけられる. set_vertex_attr, set_edge_attr
  • 属性値を確認graph_attr(g)
attr_g <- make_ring(10) %>%
  set_vertex_attr("label", value = LETTERS[1:10]) %>%
  set_edge_attr("label", value = 1:10) 

vertex_attr(attr_g)
edge_attr(attr_g)

plot(attr_g)

## $label
##  [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J"
## 
## $label
##  [1]  1  2  3  4  5  6  7  8  9 10

6.5 連結成分を分割.

  • 連結成分の確認. components, clusters
  • 連結成分ごとに分割 decompose, decompose.graph. その際min.verticesで連結成分のノード数指定
    • ノード数2以上の連結成分のリストdecompose(g, min.vertices = 2)
set.seed(1) 
g <- random.graph.game(n = 20, p = 0.1, directed = F) %>%
  set_vertex_attr(., name = "label", value = LETTERS[1:vcount(.)])

# 連結成分の確認
# # membership: 各ノードが属している連結成分, csize:連結成分のサイズ, no:連結成分の数
(cmp <- components(g))

# 連結成分ごとに分割decompose (リストが返る)
dg <- decompose(g, min.vertices = 2)

par(mfrow = c(1, cmp$no))
invisible(lapply(dg, function(x)plot(x)))

# 連結成分のなかにある指定ノードを含むグラフを抽出
v <- c("L", "S")
sub_dg <- sapply(dg, function(x) if(any(V(x)$label %in% v)){x}else{NULL})
l_sub_dg <- sub_dg[!sapply(sub_dg, is.null)]

par(mfrow = c(1, cmp$no))

invisible(lapply(l_sub_dg, function(x)plot(x)))

## $membership
##  [1] 1 1 1 1 1 1 2 3 2 1 2 2 2 1 1 2 1 1 4 2
## 
## $csize
## [1] 11  7  1  1
## 
## $no
## [1] 4

6.6 サブグラフ.

  • 指定ノードのみからなるサブグラフinduced_subgraph
  • ego_size, ego, make_ego_graph
  • subgraph_centrality
g <- make_graph(c("A","B", "A","C", "D","E", "F","G", "H","I"), directed = F)
 
# 指定ノードのみのサブグラフ
subv <- c('A','C','H') 
g2 <- induced_subgraph(graph = g, vids = subv)

# 指定ノードと接続しているノードを含めたサブグラフ
subg <- function(x, subv){
  deg <- decompose(x, mode = "weak")
  
  vnei <- unique(unlist(sapply(deg, FUN = function(s){
    if (any(V(s)$name %in% subv)) V(s)$name else NULL})))
  
  induced_subgraph(graph = g, vids = vnei)
}
g3 <- subg(g, subv)


par(mfrow = c(1,3))
plot(g)
plot(g2, main = "sub-graph with selected node")
plot(g3, main = "sub-graph with connected node")

g <- make_ring(8)
V(g)$name <- c("A", "B", "C", "D", "E", "F", "G", "H")
subg <- make_ego_graph(g, nodes = subv)
invisible(lapply(subg, plot))

g <- make_ring(10)
ego_size(g, 0, 1:3)
ego_size(g, 1, 1:3)
ego_size(g, 2, 1:3)
ego(g, 0, 1:3)
ego(g, 1, 1:3)
ego(g, 2, 1:3)

# attributes are preserved
V(g)$name <- c("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")
make_ego_graph(g, 2, 1:3)

# connecting to the neighborhood
g <- make_ring(10)
g <- connect(g, 2)
## [1] 1 1 1
## [1] 3 3 3
## [1] 5 5 5
## [[1]]
## + 1/10 vertex, from a206d30:
## [1] 1
## 
## [[2]]
## + 1/10 vertex, from a206d30:
## [1] 2
## 
## [[3]]
## + 1/10 vertex, from a206d30:
## [1] 3
## 
## [[1]]
## + 3/10 vertices, from a206d30:
## [1]  1  2 10
## 
## [[2]]
## + 3/10 vertices, from a206d30:
## [1] 2 1 3
## 
## [[3]]
## + 3/10 vertices, from a206d30:
## [1] 3 2 4
## 
## [[1]]
## + 5/10 vertices, from a206d30:
## [1]  1  2 10  3  9
## 
## [[2]]
## + 5/10 vertices, from a206d30:
## [1]  2  1  3 10  4
## 
## [[3]]
## + 5/10 vertices, from a206d30:
## [1] 3 2 4 1 5
## 
## [[1]]
## IGRAPH 8c88f9b UN-- 5 4 -- Ring graph
## + attr: name (g/c), mutual (g/l), circular (g/l), name (v/c)
## + edges from 8c88f9b (vertex names):
## [1] a--b b--c a--j i--j
## 
## [[2]]
## IGRAPH e2b7e1f UN-- 5 4 -- Ring graph
## + attr: name (g/c), mutual (g/l), circular (g/l), name (v/c)
## + edges from e2b7e1f (vertex names):
## [1] a--b b--c c--d a--j
## 
## [[3]]
## IGRAPH d1d9de5 UN-- 5 4 -- Ring graph
## + attr: name (g/c), mutual (g/l), circular (g/l), name (v/c)
## + edges from d1d9de5 (vertex names):
## [1] a--b b--c c--d d--e