本文へスキップ
からだにいいもの

Rのトピックスを中心に『まだ、まだ、知らない、役に立つ情報?』を発信します。

Rで解析:ネットワーク図をわかりやすくプロット「netplot」パッケージ

「netplot」パッケージは、ggplot2と同じgridグラフィックスシステムの上に構築されたネットワーク描画エンジンです。最大の特徴は、既定値のまま実行するだけで見栄えのするネットワーク図が得られる点にあります。具体的には、描画領域に合わせて頂点やエッジのサイズを自動でスケーリングし、直線ではなく湾曲したエッジを描き、始点(ego)から終点(alter)へ向けてエッジの色をなめらかに混ぜ合わせる、といった処理が可能です。igraphやnetworkのオブジェクト、隣接行列をそのまま渡せるため、既存の解析フローにも組み込みやすくなっています。さらに、属性に応じた色分け、凡例の追加、グラデーション色の線分、円グラフの重ね描き、クリックした頂点の情報取得など、図表現を補助する関数も一通り揃っています。

パッケージバージョンは0.4-0。Windows 11 x64 (build 26200)のR version 4.6.1で確認しています。

パッケージのインストール

下記コマンドを実行してください。

# パッケージのインストール
install.packages("netplot")
install.packages("igraph")
install.packages("gridExtra")
install.packages("magrittr")

# パッケージの読み込み
library("netplot")
# ネットワークオブジェクトの生成・操作に使用
library("igraph")
# 複数のプロットを並べて表示するために使用
library("gridExtra")
# パイプ演算子を使用するために読み込み
library("magrittr")
スポンサーリンク

コマンド例

詳細はコメント、パッケージのヘルプを確認してください。

まずnplot()でネットワークを描画します。頂点や辺の色は、make_vertex_colors()などのmake_colors()系関数で属性から一括生成でき、エッジの色はego()とalter()を用いた片側式で始点・終点の色を混ぜ合わせられます。nplot_legend()で凡例を追加でき、segments_gradient()でグラデーション色の線分を、piechart()で柔軟な円グラフを重ね描きできます。最後に、作成したプロット上でlocate_vertex()を使うと、クリックした頂点の情報を取得できます。

頂点の色や形状を属性に応じて設定しネットワーク図をプロット:nplotコマンド

オプション意味初期値
xグラフオブジェクト。igraph、network、行列オブジェクトに対応
layout頂点のx/y座標を表す2列の数値行列
vertex.size頂点の絶対サイズ(0〜1)。片側式で数値属性からマッピング可能1
bg.col背景色“transparent”
vertex.nsides頂点を描く多角形の辺の数(3で三角形、100で円に近づく)10
vertex.color頂点の色。片側式で属性から色分け可能grDevices::hcl.colors(1)
vertex.size.range頂点サイズの最小・最大とスケールの曲率c(0.01, 0.03, 4)
vertex.frame.color頂点の枠線の色NULL
vertex.rot頂点多角形の回転角度(ラジアン)0
vertex.frame.prop枠が頂点に占める割合(0〜1)0.2
vertex.label頂点ラベルの文字ベクトルNULL
vertex.label.fontsizeラベルのフォントサイズ(数値ベクトル)NULL
vertex.label.colorラベルの色(長さvcount(x)のベクトル)adjustcolor(“black”, alpha.f = 0.8)
vertex.label.fontfamilyラベルのフォントファミリ(長さvcount(x)の文字ベクトル)“sans”
vertex.label.fontfaceフォントの字体(grid::gpar参照)“plain”
vertex.label.showvertex.sizeの上位から表示するラベルの割合0.3
vertex.label.rangeラベルフォントサイズの相対スケール(ポイント、2〜3要素)c(5, 15)
edge.width辺の相対的な幅の数値ベクトル。値は正規化されedge.width.rangeの範囲に変換される。~ weightのような片側式でも指定可能1
edge.width.range辺幅をマッピングする最小・最大値(ポイント)。NULLならスケーリングしないc(1, 2)
edge.arrow.size矢印のサイズ(0〜1)NULL
edge.color辺の色のベクトル。HEXや組み込み色を使用可能。NULLのときはegoとalterの頂点色を混ぜて決定する~ego(alpha = 0.1, col = “gray”) + alter
edge.curvature辺の曲率(ラジアン)の数値ベクトルpi/3
edge.line.lty線種のベクトル“solid”
edge.line.breaks辺(弧)を近似する頂点数5
sample.edgesサンプリングする辺の割合(0〜1)1
skip.vertex論理値。TRUEのとき頂点を描画しないFALSE
skip.edges論理値。TRUEのとき辺を描画しないFALSE
skip.arrows論理値。TRUEのとき矢印を描画しないskip.edges
add論理スカラーFALSE
zero.margins論理スカラーTRUE
edgelistエッジリスト
y無視されるNULL
newpage論理値。TRUEのときgrid::grid.newpage()を呼び出すTRUE
legend論理値。TRUEのとき凡例を追加するTRUE
### データ例の作成#####
# 乱数シードを固定して再現性を確保
set.seed(314)

# 4グループのネットワークを生成
# 各島は15頂点、島内は密(確率0.4)、島どうしは3本の橋で接続
g <- igraph::sample_islands(4, 15, 0.4, 3)

# 各頂点にグループ属性を付与
V(g)$community <- rep(c("A", "B", "C", "D"), each = 15)

# 各頂点の次数を属性として保存
V(g)$deg <- degree(g)
########

### オプションを設定しないでプロット#####
# igraph標準のプロット
#plot(g)
# netplotコマンドでプロット
nplot(g)
########

### 色はグループ、形状はグループ、サイズは次数を片側式でマッピングしてプロット#####
nplot(g, vertex.color  = ~ community,
      vertex.nsides = ~ community,
      vertex.size   = ~ deg)
#####

・オプションを設定しないでプロット

・色はグループ、形状はグループ、サイズは次数を片側式でマッピングしてプロット

各頂点と辺に使用するカラーベクトルを作成:make_vertex_colorsコマンド

オプション意味初期値
dat色を生成するためのデータベクトル
categorical論理値。TRUEにすると色をカテゴリとして扱うFALSE
color_mapパレットを生成する関数grDevices::hcl.colors
xnetworkまたはigraphクラスのグラフ
vattr文字列。色の生成に用いる頂点変数名
eattr文字列。色の生成に用いる辺変数名
### データ例の作成#####
# 乱数シードを固定
set.seed(1618)

# 50頂点のランダムグラフ(Erdős–Rényiモデル)を生成
g <- igraph::sample_gnp(50, 0.08)

# 各頂点に3つの役割のいずれかを割り当てる
V(g)$role <- sample(c("生産", "物流", "販売"), 50, replace = TRUE)
########

# 役割("生産", "物流", "販売")ごとに色分けしたカラーベクトルを作成
col <- make_vertex_colors(g, "role", categorical = TRUE)

# 作成した色ベクトルを頂点の塗り・枠・エッジに適用して描画
nplot(g) %>%
  set_vertex_gpar("core", fill = col, col = col) %>%
  set_vertex_gpar("frame", fill = col, col = col, alpha = .7) %>%
  set_edge_gpar(col = "gray50", fill = "gray50", alpha = .5)

エッジの色を始点(ego)と終点(alter)の色の混合で指定する:netplot-formulaeコマンド

オプション意味初期値
xnetplotオブジェクト
col有効な色を指定。単一の色やベクトルでも可
alphaアルファレベル(透過度)
env内部使用のみ
type内部使用のみ
mixegoとalterの色を混合する割合1
postfix内部使用のみNULL
# 6頂点の有向スターグラフ(中心から外向き)を作成
g <- make_star(6, mode = "out")

# 乱数シードを固定して再現性を確保
set.seed(555)

# 頂点ごとに異なる色を付けてネットワークを描画
np <- nplot(g, vertex.color = grDevices::hcl.colors(6), vertex.size.range = c(.1, .1))

# エッジの線幅を太くして色の混ざり方を見やすくする
np <- set_edge_gpar(np, lwd = 4)

# 各パネルの上部に見出しを付けるためのヘルパー関数
# arrangeGrob()のtop引数に文字列を渡すと、そのグロブの上に見出しが描かれる
titled <- function(x, title) {
  arrangeGrob(x, top = grid::textGrob(title, gp = grid::gpar(fontsize = 15, col = "red")))
}

# ego(始点)とalter(終点)の色の混ぜ方を変えた6パターンを並べて描画
grid.arrange(
  # 既定のエッジ色(始点側は薄いグレー、終点は頂点色)
  titled(np, "既定"),
  # 始点と終点、それぞれの頂点色を混ぜ合わせる
  titled(np %>% set_edge_gpar(col =~ ego + alter), "ego + alter"),
  # 始点側を透明にし、終点の色へフェードインさせる
  titled(np %>% set_edge_gpar(col =~ ego(alpha = 0) + alter), "ego(alpha=0) + alter"),
  # 終点側を透明にし、始点の色からフェードアウトさせる
  titled(np %>% set_edge_gpar(col =~ ego + alter(alpha = 0)), "ego + alter(alpha=0)"),
  # 混合の重みを終点側に全振りし、ほぼ終点色で描く
  titled(np %>% set_edge_gpar(col =~ ego(mix = 0) + alter(mix = 1)), "ego(mix=0) + alter(mix=1)"),
  # 混合の重みを始点側に全振りし、ほぼ始点色で描く
  titled(np %>% set_edge_gpar(col =~ ego(mix = 1) + alter(mix = 0)), "ego(mix=1) + alter(mix=0)")
)

ネットワーク図に凡例を追加:nplot_legendコマンド

オプション意味初期値
gnetplotオブジェクト
labelsラベルの文字ベクトル
pchプロット記号(graphics::points()参照)
gpgrid::gparオブジェクトgrid::gpar()
packgrob.argsgrid::packGrob()に渡す引数のリストlist(side = “left”)
xnetplot_legendオブジェクト
y未使用NULL
newpage論理値。TRUEのときgrid::grid.newpage()を呼び出すTRUE
### データ例を作成#####
# 乱数シードを固定
set.seed(808)
# 100頂点のランダムグラフを生成
g <- sample_gnp(100, 0.04)
# 各頂点に2種類の形状を割り当て(4は四角形、10は円に近い多角形)
V(g)$shape <- sample(c(4, 10), 100, replace = TRUE)
########

# 形状と色を属性に応じて設定してネットワークを描画
np <- nplot(
  g,
  vertex.nsides = V(g)$shape,
  vertex.color  = ifelse(V(g)$shape == 4, "darkorange", "steelblue")
)

# プロットに凡例を追加(既定では左側に配置される)
# labelsは項目名、pchは各項目の記号(22=四角形、21=円、NA=線)
# gpのfill・lwd・colで、記号の塗り色・線の太さ・線の色を項目ごとに指定する
nplot_legend(
  np,
  labels = c("四角形の頂点", "円形の頂点", "エッジ"),
  pch    = c(22, 21, NA),
  gp     = gpar(
    fill = c("darkorange", "steelblue", NA),
    lwd  = c(NA, NA, 1),
    col  = c(NA, NA, "gray40")
  )
)

辺をカラーグレードで描画し、グラデーション効果を付与:segments_gradientコマンド

オプション意味初期値
xgrDevices::xy.coordsに渡される座標
ygrDevices::xy.coordsに渡される座標NULL
col色のグラデーション関数(grDevices::colorRamp参照)colorRamp2(c(“transparent”, “black”), TRUE)
lendgraphics::segmentsに渡される1
# 乱数シードを固定
set.seed(999)
# 2次元のランダムウォークの座標を生成
x <- cbind(cumsum(rnorm(400, sd = .25)), cumsum(rnorm(400, sd = .25)))

# 線分の本数(座標点の数より1つ少ない)
n <- nrow(x) - 1
# 始点から終点へ向かって太くなる線幅ベクトルを用意
lwd <- seq(0.5, 6, length.out = n)

# 描画領域だけを準備(線はまだ描かない)
plot(x, type = "n")

# 黄→赤のグラデーションで、色が濃く(赤く)なるほど線を太く描画
# colにcolorRamp2()で作った色関数、lwdは...経由でsegments()へ渡る
segments_gradient(x, col = colorRamp2(c("gold", "firebrick")), lwd = lwd)

円環上に分割された領域を色分けして表示:piechartコマンド

オプション意味初期値
x各スライスの面積を表す数値ベクトル
labels文字ベクトル(graphics::text()に渡される)names(x)
radius各スライスの半径(スカラーも可)1
doughnut内側の円(ドーナツ)の半径0
origin原点の座標(長さ2の数値ベクトル)c(0, 0)
edgesスライスの曲線の滑らかさ200
slice.offスライスを原点から離す距離0
init.angle描画を開始する角度(度)0
last.angle描画を終了する角度(度)360
tick.len目盛りの長さ(半径に対する割合)0.1
text.argsgraphics::text()に渡す追加引数のリストlist()
segments.args目盛り描画時にgraphics::segments()へ渡す引数のリストlist()
skip.plot.slices論理スカラー。FALSEのときスライスを描画しないFALSE
add論理スカラー。TRUEのとき現在のデバイスに追加するFALSE
rescale論理スカラー。TRUEのとき縦横比を保つようy座標をスケーリングするTRUE
# 各カテゴリの値
vals <- c(8, 5, 12, 3, 6)

# 一番外側のリング(値をラベルとして表示)
piechart(vals, col = grDevices::hcl.colors(5, "Teal"),
    border = NA, doughnut = .5, radius = .8, labels = vals)

# 内側のリング(同じ値を重ねて二重ドーナツにする)
piechart(vals, col = grDevices::hcl.colors(5, "Peach"),
    border = NA, doughnut = .25, radius = .5, add = TRUE)

# 各スライスを外側にずらして強調した円グラフ
piechart(c(30, 20, 35, 15),
    col = grDevices::hcl.colors(4, "Sunset"),
    slice.off = c(.05, 0, .1, 0),
    labels = c("東", "西", "南", "北"))

プロット内でクリックされた頂点の情報を取得:locate_vertexコマンド

オプション意味初期値
xnetplotオブジェクトNULL
# 乱数シードを固定
set.seed(246)
# 60頂点のランダムグラフを生成
g <- sample_gnp(60, 0.07)

# ネットワークを描画
nplot(g)

# クリックした頂点の名前・座標・ビューポートを取得
res <- locate_vertex()

# 取得した情報を表示
print(res)


この記事が誰かの役に立ちますように。

スポンサーリンク
価格および配送状況は変更される場合があります。購入時は商品ページをご確認ください。
当サイトに表示されている商品情報はAmazonから提供されたものであり、更新または削除される場合があります。
karada-goodはAmazonアソシエイトとして、適格販売により収入を得ています。