グラフ作成.
エッジリストからグラフオブジェクト生成.
- エッジリストをvectorで与える.
make_graph
ベクトルからグラフ生成.
- ノードラベルを名に値がわりふられる
V(g)$name
- エッジリストをmatrixで与える.
graph_from_edgelist()
, graph.edgelist()
- エッジリストを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
ノード・エッジを直接記述する.
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( ~ )")

隣接行列からグラフオブジェクトの生成.
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値データに変換して重みなしグラフを生成
- 相関係数を重みとする
# 相関係数行列を -> 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)

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])
}))



特殊なグラフ.
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)")

スケールフリーグラフ, ランダムグラフ.
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")

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)

グラフ描画.
グラフ描画.
?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"
)

コミュニティーごとに色分け.
# コミュニティー検出
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)

サークルレイアウトで次数の大きい順に配置layout_in_circle(g, order)
.
lay.crc <- layout_in_circle(g, order = order(degree(g), decreasing = T))
plot(g, layout = lay.crc)

色々なレイアウト関数. 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"
グラフオブジェクトの操作.
ノード数, エッジ数, 連結成分.
- ノード数, エッジ数, 次数
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) # 隣接ノード
エッジリスト, 隣接リスト, 隣接行列 取り出し.
- エッジリスト(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] # 隣接行列
ノード, エッジの追加・削除.
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)))

ノード, エッジの属性値を追加.
- 属性値の名前は自由につけられる.
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
連結成分を分割.
- 連結成分の確認.
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
サブグラフ.
- 指定ノードのみからなるサブグラフ
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