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

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

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列目に点の名前を入れます。

オプション意味初期値
mappingaesで指定するマッピング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)

観光地の移動を線で結び、点の大きさを観光客数にしてプロット

線にラベルを付ける:geom_edge_textコマンド

線の中ほどに文字を置くレイヤーです。graph_from_data_frameで作ったグラフなら、元のデータフレームの3列目以降(ここでは移動時間のjikan)をaesでそのまま使えます。

オプション意味初期値
mappingaesで指定するマッピング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)

移動時間を線に沿って少しずらして表示し、観光地名を付けてプロット

点を円周に並べる: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()

観光地をつながりの多い順に円周へ並べてプロット


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

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