Rで解析:igraphのネットワークをggplot2でプロットする「ggtangle」パッケージ
「ggtangle」パッケージは、ネットワーク図をggplot2のグラフとして作るパッケージです。igraphのグラフオブジェクトを渡すと点と線の座標に直され、点・線・文字をggplot2のレイヤーとして重ねてプロットできます。名前付きのリストを渡すと、カテゴリとそこに含まれる項目のつながりを1行で図にできます。ggplot2とigraphの上に乗る拡張なので、色や大きさ、凡例はggplot2の書き方で整えられます。ggplot2に慣れていて、つながりのデータもいつもの書き方で見せたい人に向いていると考えます。
パッケージバージョンは0.1.4。Windows 11 x64 (build 26200)のR version 4.6.1で確認しています。
パッケージのインストール
# パッケージのインストール
install.packages("ggtangle")
# パッケージの読み込み
library("ggtangle")
ggtangle v0.1.4 Learn more at https://yulab-smu.top/
# コマンド例実行で必要なパッケージを読み込み
library("igraph")
Attaching package: 'igraph'
The following objects are masked from 'package:stats':
decompose, spectrum
The following object is masked from 'package:base':
union
library("ggplot2")コマンド例
詳細はコメント、パッケージのヘルプを確認してください。
ネットワーク図は、物(ノード)を点で、物どうしのつながり(エッジ)を線で表した図です。ggtangleでは、igraphのグラフオブジェクトをggplotコマンドに渡すと、点の座標とつながりの情報を持ったggplotオブジェクトになります。そこへ線のレイヤー(geom_edge)や、ggplot2の点・文字のレイヤーを足していきます。
ここでは2つの架空データを使います。1つは京都の直売所ごとの取扱品目(名前付きのリスト)、もう1つは京都の観光地どうしの移動時間(データフレーム)です。データは最初にまとめて作り、各コマンドで使い回します。
# 直売所ごとの取扱品目を名前付きのリストで作成
chokubai <- list(
"大原の里" = c("賀茂なす", "九条ねぎ", "聖護院かぶ", "京たけのこ", "万願寺とうがらし"),
"亀岡の駅" = c("九条ねぎ", "丹波黒大豆", "丹波栗", "万願寺とうがらし"),
"宇治の市" = c("宇治茶", "京たけのこ", "九条ねぎ"),
"舞鶴の港" = c("万願寺とうがらし", "丹波栗", "伊根の寒ぶり")
)
# 品目ごとの売上の前年比(対数比)を名前付きのベクトルで作成
zenen <- c(
"賀茂なす" = 1.8, "九条ねぎ" = -0.6, "聖護院かぶ" = 0.4,
"京たけのこ" = -1.5, "万願寺とうがらし" = 2.1, "丹波黒大豆" = 0.9,
"丹波栗" = -0.3, "宇治茶" = 1.2, "伊根の寒ぶり" = -2.0
)
# 観光地どうしの移動時間(分)をデータフレームで作成
idou <- data.frame(
from = c("京都駅", "京都駅", "京都駅", "嵐山", "伏見稲荷", "宇治", "大原"),
to = c("嵐山", "伏見稲荷", "大原", "鞍馬", "宇治", "平等院", "鞍馬"),
jikan = c(25, 10, 60, 70, 30, 10, 40)
)
# データフレームからigraphのグラフオブジェクトを作成
g <- graph_from_data_frame(idou)
# 観光地ごとの1日あたりの観光客数(百人)を作成
spot <- data.frame(
label = c("京都駅", "嵐山", "伏見稲荷", "大原", "宇治", "鞍馬", "平等院"),
kankoukyaku = c(300, 180, 220, 60, 90, 40, 120)
)カテゴリと項目のつながりをプロット:cnetplotコマンド
名前付きのリストを渡すと、リストの名前(カテゴリ)と中身(項目)を線でつないだネットワーク図を作ります。複数のカテゴリに出てくる項目は、それらのカテゴリの間に置かれます。
| オプション | 意味 | 初期値 |
|---|---|---|
| x | 入力するデータ。名前付きのリストなど | なし |
| layout | ネットワークの配置 | “nicely” |
| showCategory | 表示するカテゴリ。数値1つで先頭からn個、数値ベクトルで番号指定(例:c(1, 10, 53))、文字列ベクトルで名前指定 | 5 |
| color_category | カテゴリの点の色 | “#E5C494” |
| size_category | カテゴリの点の相対的な大きさ | 1 |
| color_item | 項目の点の色 | “#B3B3B3” |
| size_item | 項目の点の相対的な大きさ | 1 |
| color_edge | 線の色。”category”を指定するとカテゴリごとに色分け | “grey” |
| size_edge | 線の相対的な太さ | 0.5 |
| categorySizeBy | カテゴリの点の大きさを決める式またはformula(例:itemNum、~ -log10(p.adjust)) | ~itemNum |
| node_label | ラベルを付ける点。”all”、”none”、”category”、”item”、”exclusive”、”share”から指定 | “all” |
| node_label_size | ラベルの文字の大きさ。NULLは既定の大きさ | NULL |
| foldChange | 項目の点を色分けする数値(名前付きのベクトル) | NULL |
| fc_threshold | 項目を絞り込むfoldChangeの絶対値のしきい値 | NULL |
| hilight | 強調するカテゴリ | “none” |
| hilight_alpha | 強調しないカテゴリの透明度 | 0.3 |
| … | その他のオプション。curvatureで線を曲げられる(例:curvature = 0.2) | なし |
# 直売所と取扱品目のつながりをプロット
# 直売所の点の大きさは取扱品目の数
cnetplot(chokubai)
# 品目の点を前年比で色分けし、線を直売所ごとに色分けしてプロット
# ラベルは直売所と、複数の直売所で扱う品目だけに付ける
cnetplot(chokubai,
foldChange = zenen,
color_edge = "category", node_label = "share"
)直売所と取扱品目のつながりをプロット直売所の点の大きさは取扱品目の数

品目の点を前年比で色分けし、線を直売所ごとに色分けしてプロットラベルは直売所と、複数の直売所で扱う品目だけに付ける

つながりの線を引く:geom_edgeコマンド
ggplot(igraphのグラフ)に足すと、つながりを線で引くレイヤーになります。点と文字はggplot2のgeom_pointやgeom_textで重ねます。%<+%で点ごとのデータフレームを付け足すと、その列を色や大きさに使えます。付け足すデータフレームは、1列目に点の名前を入れます。
| オプション | 意味 | 初期値 |
|---|---|---|
| mapping | aesで指定するマッピング | NULL |
| data | プロットするデータ | NULL |
| geom | 線を引くレイヤー | geom_segment |
| … | geomに渡すオプション | なし |
# 配置を毎回同じにするため乱数を固定
set.seed(1)
# 観光地の移動を線で結び、点の大きさを観光客数にしてプロット
ggplot(g) %<+% spot +
geom_edge(color = "grey60") +
geom_point(aes(size = kankoukyaku), color = "darkgreen") +
geom_text(aes(label = label), nudge_y = 0.15)観光地の移動を線で結び、点の大きさを観光客数にしてプロット

<おすすめのRに関する書籍です>
線にラベルを付ける:geom_edge_textコマンド
線の中ほどに文字を置くレイヤーです。graph_from_data_frameで作ったグラフなら、元のデータフレームの3列目以降(ここでは移動時間のjikan)をaesでそのまま使えます。
| オプション | 意味 | 初期値 |
|---|---|---|
| mapping | aesで指定するマッピング | NULL |
| data | プロットするデータ | NULL |
| geom | 文字を置くレイヤー | geom_text |
| angle_calc | 文字の角度の決め方。”along”で線に沿わせる、”none”で水平 | “none” |
| label_dodge | 文字を線からずらす距離 | NULL |
| … | geomに渡すオプション | なし |
# 配置を毎回同じにするため乱数を固定
set.seed(1)
# 移動時間を線に沿って少しずらして表示し、観光地名を付けてプロット
ggplot(g) +
geom_edge(color = "grey60") +
geom_edge_text(aes(label = paste0(jikan, "分")),
angle_calc = "along", label_dodge = 0.05,
size = 3.5, color = "firebrick"
) +
geom_point(size = 4, color = "darkgreen") +
geom_text(aes(label = name), nudge_y = 0.15)移動時間を線に沿って少しずらして表示し、観光地名を付けてプロット

<おすすめのRに関する書籍です>
点を円周に並べる:layout_circularコマンド
点を円周上に並べる配置を計算します。ggplotコマンドのlayoutに渡して使い、sort.byはggplotコマンドのオプションとして書くとlayout_circularに渡ります。sort.byに”degree”を指定すると、つながりの多い点から順に並びます。
| オプション | 意味 | 初期値 |
|---|---|---|
| graph | グラフオブジェクト | なし |
| sort.by | 並べる順を決める点の属性名。”degree”でつながりの数 | NULL |
| … | igraph::layout_in_circleに渡すオプション | なし |
# 観光地をつながりの多い順に円周へ並べてプロット
ggplot(g, layout = layout_circular, sort.by = "degree") +
geom_edge(color = "grey60") +
geom_point(size = 4, color = "darkgreen") +
geom_text(aes(label = name), nudge_y = 0.1) +
coord_fixed()観光地をつながりの多い順に円周へ並べてプロット

<おすすめのRに関する書籍です>
この記事が誰かの役に立ちますように。