Rで解析:パス図をデータフレームからggplot2で組み立てる「ggsem」パッケージ
「ggsem」パッケージは、構造方程式モデリング(SEM)のパス図を、ggplot2のグラフとして組み立てるパッケージです。変数を表す四角や楕円、矢印、文字、自己ループを、位置や色を1行ずつ並べたデータフレームで渡すとプロットになります。ggplot2の上に乗る拡張なので、軸の範囲や余白はggplot2のオブジェクトとして整えられます。付属のShinyアプリで配置を決めて書き出したCSVも同じ形で読み込めます。論文や発表用のパス図を、コードで作り直せる形で残したい人に役立つのではないかと考えます。
パッケージバージョンは1.0.1。Windows 11 x64 (build 26200)のR version 4.6.1で確認しています。
<おすすめのRに関する書籍です>
パッケージのインストール
# パッケージのインストール
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本の矢印を置く。栽培面積→品質評価だけ破線

<おすすめのRに関する書籍です>
変数名をプロット: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
<おすすめのRに関する書籍です>
軸の範囲を確かめる:get_axis_rangeコマンド
ggplotオブジェクトのx軸とy軸の範囲をリストで返します。範囲を広げる前に、今の範囲を確かめるのに使います。
| オプション | 意味 | 初期値 |
|---|---|---|
| plot | csv_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_range | x軸の範囲(長さ2の数値ベクトル)。NULLで今の範囲のまま | NULL |
| y_range | y軸の範囲(長さ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_percent | x軸の左端を広げる割合(%) | 0 |
| x_adjust_right_percent | x軸の右端を広げる割合(%) | 0 |
| y_adjust_bottom_percent | y軸の下端を広げる割合(%) | 0 |
| y_adjust_top_percent | y軸の上端を広げる割合(%) | 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%の余白を足す

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