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

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

Rで解析:パス図をデータフレームからggplot2で組み立てる「ggsem」パッケージ

「ggsem」パッケージは、構造方程式モデリング(SEM)のパス図を、ggplot2のグラフとして組み立てるパッケージです。変数を表す四角や楕円、矢印、文字、自己ループを、位置や色を1行ずつ並べたデータフレームで渡すとプロットになります。ggplot2の上に乗る拡張なので、軸の範囲や余白はggplot2のオブジェクトとして整えられます。付属のShinyアプリで配置を決めて書き出したCSVも同じ形で読み込めます。論文や発表用のパス図を、コードで作り直せる形で残したい人に役立つのではないかと考えます。

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

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

# パッケージのインストール
install.packages("ggsem")

# パッケージの読み込み
library("ggsem")
Documentation website of ggsem: smin95.github.io/ggsem/

# コマンド例実行で必要なパッケージを読み込み
library("ggplot2")
スポンサーリンク

コマンド例

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

構造方程式モデリング(SEM)は、変数どうしの関係を矢印でつないだパス図で表し、その強さを推定する手法です。ggsemでは、パス図を「点(四角や楕円)」「線(矢印)」「文字」「自己ループ」の4つの部品に分け、それぞれをデータフレームで用意します。

ここでは、宇治茶の栽培面積が品質評価と売上に、品質評価が売上につながるパス図を例にします。部品のデータは最初にまとめて作り、各コマンドで使い回します。

# 変数の箱:栽培面積・売上は四角、品質評価は楕円
points_df <- data.frame(
  x = c(-20, 0, 20), y = c(0, 15, 0),
  shape = c("rectangle", "oval", "rectangle"),
  color = c("#D9EAD3", "#FCE5CD", "#CFE2F3"), size = 40,
  border_color = "#38761D", border_width = 1.5, alpha = 1,
  width_height_ratio = 1.6, orientation = 0,
  lavaan = FALSE, network = FALSE, locked = FALSE, group = 1
)

# 箱をつなぐ矢印:栽培面積→売上、栽培面積→品質評価(破線)、品質評価→売上
lines_df <- data.frame(
  x_start = c(-12, -16, 7), y_start = c(0, 5, 10),
  x_end = c(12, -7, 16), y_end = c(0, 10, 5),
  ctrl_x = NA, ctrl_y = NA, ctrl_x2 = NA, ctrl_y2 = NA,
  curvature_magnitude = NA, rotate_curvature = NA, curvature_asymmetry = NA,
  type = "Straight Arrow", color = "#000000", end_color = NA,
  color_type = "Single", gradient_position = NA,
  width = 1.2, alpha = 1, arrow = TRUE, arrow_type = "closed",
  arrow_size = 0.1, two_way = FALSE, lavaan = FALSE, network = FALSE,
  line_style = c("solid", "dashed", "solid"), locked = FALSE, group = 1
)

# 箱の中に置く変数名
annotations_df <- data.frame(
  text = c("栽培面積", "品質評価", "売上"),
  x = c(-20, 0, 20), y = c(0, 15, 0),
  font = "sans", size = 14, color = "#000000", fill = NA, angle = 0,
  alpha = 1, fontface = "bold", math_expression = FALSE,
  lavaan = FALSE, network = FALSE, locked = FALSE,
  group_label = FALSE, loop_label = FALSE, group = 1
)

# 売上の誤差分散を表す自己ループ(箱の下)
loops_df <- data.frame(
  x_center = 20, y_center = -7, radius = 2, color = "#CC0000",
  width = 1, alpha = 1, arrow_type = "closed", arrow_size = 0.1,
  gap_size = 0.2, loop_width = 1, loop_height = 1, orientation = 180,
  lavaan = FALSE, two_way = FALSE, locked = FALSE, group = 1
)

変数の箱をプロット:draw_pointsコマンド

四角や楕円などの図形を、ggplotオブジェクトに足すレイヤーとして返します。

オプション意味初期値
points_data図形のデータフレーム。列は x・y(中心の座標)、shape(”circle”・”square”・”triangle”・”rectangle”・”oval”・”diamond”)、color(塗りの色)、size(大きさ)、border_color(枠線の色)、border_width(枠線の太さ)、alpha(透明度:0〜1)、width_height_ratio(幅と高さの比)、orientation(回転角度:度)なし
zoom_level図形の大きさの倍率1
# 3つの変数の箱を置き、縦横の縮尺をそろえて表示範囲を決める
ggplot() +
  draw_points(points_df, zoom_level = 1.2) +
  coord_fixed(xlim = c(-35, 35), ylim = c(-15, 25))

3つの変数の箱を置き、縦横の縮尺をそろえて表示範囲を決める

矢印をプロット:draw_linesコマンド

直線や曲線、矢印をレイヤーとして返します。線の種類(実線・破線・点線)や、始点から終点への色のグラデーションも指定できます。

オプション意味初期値
lines_data線のデータフレーム。列は x_start・y_start(始点)、x_end・y_end(終点)、ctrl_x・ctrl_y(曲線の制御点)、type(”Straight Line”・”Curved Line”・”Straight Arrow”・”Curved Arrow”)、color(始点の色)、end_color(終点の色)、color_type(”Single”で単色・”Gradient”でグラデーション)、gradient_position(色が切り替わる位置:0〜1)、width(太さ)、alpha(透明度)、arrow(矢印を付けるか)、arrow_type(”open”・”closed”など)、arrow_size(矢じりの大きさ)、two_way(両向きの矢印にするか)、line_style(”solid”・”dashed”・”dotted”)なし
zoom_level線の太さと矢じりの大きさの倍率1
n曲線やグラデーションを補間する点の数100
# 3本の矢印を置く。栽培面積→品質評価だけ破線
ggplot() +
  draw_lines(lines_data = lines_df, zoom_level = 1.2, n = 200)

3本の矢印を置く。栽培面積→品質評価だけ破線

変数名をプロット:draw_annotationsコマンド

文字をレイヤーとして返します。フォントや太さ、回転角度を1行ずつ指定できます。

オプション意味初期値
annotations_data文字のデータフレーム。列は text(文字)、x・y(座標)、font(フォント名:”serif”など)、size(大きさ)、color(色)、angle(回転角度:度)、alpha(透明度:0〜1)、fontface(字体:”bold”など)、math_expression(数式として解釈するか)なし
zoom_level文字の大きさの倍率1
# 変数名を太字で置く
ggplot() +
  draw_annotations(annotations_df, zoom_level = 1.2)

変数名を太字で置く

自己ループ矢印をプロット:draw_loopsコマンド

自分自身に戻る矢印をレイヤーとして返します。SEMのパス図では、誤差分散を表すのに使います。

オプション意味初期値
loops_data自己ループのデータフレーム。列は x_center・y_center(中心の座標)、radius(半径)、color(色)、width(線の太さ)、alpha(透明度:0〜1)、arrow_type(”closed”・”open”)、arrow_size(矢じりの大きさ)、gap_size(ループの切れ目の大きさ:円周に対する割合)、loop_width・loop_height(幅と高さの倍率)、orientation(回転角度:度)、two_way(両端に矢じりを付けるか)なし
zoom_level線の太さと矢じりの大きさの倍率1
# 箱と重ねて、売上の下に自己ループを置く
ggplot() +
  draw_points(points_df) +
  draw_loops(loops_df, zoom_level = 1.2)

箱と重ねて、売上の下に自己ループを置く

部品をまとめてパス図にする:csv_to_ggplotコマンド

点・線・文字・自己ループのデータフレームをリストで渡し、1枚のパス図にします。Shinyアプリから書き出したCSVを読み込んだデータフレームも、そのまま渡せます。element_order は後ろに書いた部品ほど上に重なります。

オプション意味初期値
graphics_data点・線・文字・自己ループのデータフレームのリストNULL
element_order部品を重ねる順番c(“lines”, “points”, “loops”, “annotations”)
zoom_level拡大率。1より大きいと拡大、小さいと縮小1
horizontal_position図を左右にずらす量0
vertical_position図を上下にずらす量0
n曲線やグラデーションを補間する点の数100
# 4つの部品をまとめる。箱の上に矢印、いちばん上に変数名を重ねる
p <- csv_to_ggplot(
  graphics_data = list(points_df, lines_df, annotations_df, loops_df),
  element_order = c("points", "lines", "loops", "annotations")
)
Coordinate system already present.
ℹ Adding new coordinate system, which will replace the existing one.

p

軸の範囲を確かめる:get_axis_rangeコマンド

ggplotオブジェクトのx軸とy軸の範囲をリストで返します。範囲を広げる前に、今の範囲を確かめるのに使います。

オプション意味初期値
plotcsv_to_ggplotで作ったggplotオブジェクトなし
# パス図の今の軸の範囲を確かめる
get_axis_range(p)
$x_range
[1] -24.2  24.2

$y_range
[1] -10.3  18.3

軸の範囲を指定する:adjust_axis_rangeコマンド

x軸とy軸の範囲を数値で指定し直します。端で切れていた図形を、範囲を広げて全体が入るようにできます。

オプション意味初期値
plot範囲を変えるggplotオブジェクトなし
x_rangex軸の範囲(長さ2の数値ベクトル)。NULLで今の範囲のままNULL
y_rangey軸の範囲(長さ2の数値ベクトル)。NULLで今の範囲のままNULL
buffer_percent各軸の範囲に足す余白の割合(%)0
fixed_aspect_ratio縦横比を保つか。TRUEで片方の軸を合わせて調整TRUE
# 箱や自己ループが切れないよう、範囲を広げて5%の余白を足す
adjust_axis_range(p,
  x_range = c(-40, 40), y_range = c(-20, 30),
  buffer_percent = 5
)
Coordinate system already present.
ℹ Adding new coordinate system, which will replace the existing one.

箱や自己ループが切れないよう、範囲を広げて5%の余白を足す

余白を割合で広げる:adjust_axis_spaceコマンド

今の軸の範囲を、上下左右それぞれ割合で広げます。範囲を数値で決めなくても、端の余白だけ足せます。

オプション意味初期値
plot余白を変えるggplotオブジェクトなし
x_adjust_left_percentx軸の左端を広げる割合(%)0
x_adjust_right_percentx軸の右端を広げる割合(%)0
y_adjust_bottom_percenty軸の下端を広げる割合(%)0
y_adjust_top_percenty軸の上端を広げる割合(%)0
fixed_aspect_ratio縦横比を1:1に保つか。FALSEでx軸とy軸を別々に伸び縮みTRUE
# 左右に10%、下に5%、上に20%の余白を足す
adjust_axis_space(p,
  x_adjust_left_percent = 10, x_adjust_right_percent = 10,
  y_adjust_bottom_percent = 5, y_adjust_top_percent = 20
)
Coordinate system already present.
ℹ Adding new coordinate system, which will replace the existing one.

左右に10%、下に5%、上に20%の余白を足す


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

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