Rで解析:視認性に配慮したグラフ作成 ggplotplusパッケージの紹介
グラフでデータを伝える際には、色覚特性の違いにかかわらず読み取れる表現を選ぶことが重要です。配色、目盛りの間隔、凡例の位置を整えると、伝えたい内容が正確に伝わりやすくなります。しかし、ggplot2でこれらを一つずつ設定するには手間がかかります。
本パッケージは、視認性に配慮したグラフを簡単に作成できるパッケージです。文字や線の太さと配色をまとめて設定するコマンド、連続軸にのみ補助線を引くコマンド、y軸タイトルを上部へ移動するコマンドが収録されています。凡例の代わりにグラフ上へ直接ラベルを配置するコマンド、塗り分けに対応した独自の点形状を利用するコマンドも用意されています。
また、目盛りの位置を自動で調整する処理や、注目したいグループのみを強調して他を灰色にする処理も可能です。
8/9 8:30 ご指摘を受け、折れ線グラフのコードを以下内容で修正。ありがとうございます。

① X軸ラベルが数字になっていたのを月に修正
②折れ線グラフにポイントを追加し視認性を向上
パッケージバージョンは0.5.6。Windows 11 x64 (build 26200)のR version 4.6.1で確認しています。
パッケージのインストール
下記コマンドを実行してください。
# パッケージのインストール
install.packages("ggplotplus")
# パッケージの読み込み
library("ggplotplus")
# コマンド例の実行に必要なパッケージを読み込み
library("ggplot2")コマンド例
詳細はコメント、パッケージのヘルプを確認してください。本パッケージのコマンドは、ggplot2のコマンドに「+」でつないで利用します。どのコマンドが「ggplotplus」パッケージのものかがわかるように、ggplot2のコマンドには「ggplot2::」を付けて記載しています。
記事で使用するデータの作成
農産物直売所5店舗の、月別の来客数と売上高を想定したデータを作成します。以降のコマンド例は、すべてこのデータを利用します。
# 店舗名を作成
tenpo <- c("みどり直売所", "あおば直売所", "ひなた直売所",
"こもれび直売所", "かぜまち直売所")
# 月別の平均気温を作成
kion <- c(-7.2, -6.5, -1.8, 5.4, 11.6, 16.3,
20.1, 21.4, 16.8, 10.2, 2.6, -4.1)
# 店舗の立地による気温の差を作成
kion.sa <- c(0, -1.8, 1.2, -0.6, 0.4)
# 月別の来客数を作成、5店舗×12か月の順に並べる
raikyaku <- c(
420, 380, 510, 720, 1180, 1460, 1920, 2050, 1540, 1120, 640, 480,
560, 540, 610, 700, 880, 1010, 1180, 1230, 1050, 900, 700, 620,
180, 160, 240, 430, 760, 1090, 1610, 1780, 1240, 720, 330, 210,
980, 1020, 940, 820, 760, 720, 830, 900, 810, 780, 860, 1050,
310, 300, 350, 400, 470, 530, 620, 660, 570, 490, 390, 340)
# 店舗ごとの客単価を作成
tanka <- c(1450, 1180, 1620, 1320, 980)
# 直売所データを作成、売上高は来客数と客単価から万円単位で算出
chokubai <- data.frame(
store = factor(rep(tenpo, each = 12), levels = tenpo),
month = rep(1:12, times = 5),
temp = rep(kion, times = 5) + rep(kion.sa, each = 12),
visitor = raikyaku,
sales = round(raikyaku * rep(tanka, each = 12) / 10000))
# 作成したデータの確認
# head(chokubai)
# 店舗ごとの年間売上高を集計
nenkan <- aggregate(sales ~ store, data = chokubai, FUN = sum)[文字や線、配色をまとめて設定]:theme_plusコマンド
ユニバーサルデザインを意識した装飾テーマを利用できます。書き出しサイズを指定すると、文字と線の太さが内部で再調整されます。
| オプション | 意味 | 初期値 |
|---|---|---|
| … | ggplot2::theme()へ渡す追加のテーマ設定を指定 | なし |
| legend_pos | 凡例の配置を”top”、”right”、”bottom”から指定 | “top” |
| base_font_size | 文字要素の基準の大きさをポイントで指定 | 16 |
| base_linewidth | 軸線や目盛り線など線要素の基準の太さを指定 | 1.2 |
| base_rectlinewidth | 凡例の枠など矩形要素の基準の線の太さを指定 | 1.2 |
| line_color | 線要素の既定の色を指定 | “black” |
| text_color | 文字要素の既定の色を指定 | “black” |
| background_color | パネルや凡例の背景色を指定 | “#FFFEFD” |
| palette_discrete | 離散スケールに使うviridis系パレットを”A”から”H”で指定 | “D” |
| palette_continuous | 連続スケールに使うviridis系パレットを”A”から”H”で指定 | “E” |
| begin_discrete | 離散スケールで色を取り始める位置を0から1で指定 | 0 |
| end_discrete | 離散スケールで色を取り終える位置を0から1で指定 | 0.72 |
| begin_continuous | 連続スケールで色を取り始める位置を0から1で指定 | 0 |
| end_continuous | 連続スケールで色を取り終える位置を0から1で指定 | 1 |
| export_width | 書き出し時の想定の幅を指定 | 7.25 |
| export_height | 書き出し時の想定の高さを指定 | 5.95 |
| override_legend_alphasize | 凡例の大きさと透明度を本パッケージの既定値で上書きするかを指定 | TRUE |
| enable_coaching | ユニバーサルデザイン上の問題を自動で検査し助言を表示するかを指定 | TRUE |
# 店舗ごとの月別売上高をプロット
## 修正前のコード ggplot2::ggplot(chokubai, ggplot2::aes(month, sales, colour = store))
ggplot2::ggplot(chokubai, ggplot2::aes(factor(month), sales,
colour = store, group = store)) +
# 折れ線を追加
ggplot2::geom_line(linewidth = 1) +
# ポイントを追加
ggplot2::geom_point(size = 3) +
# 軸と凡例のラベルを設定
ggplot2::labs(x = "月", y = "売上高(万円)", colour = "店舗") +
# 既定値のままテーマを適用
theme_plus()
# 凡例の位置や配色、書き出しサイズを指定してプロット
## 修正前のコード ggplot2::ggplot(chokubai, ggplot2::aes(month, sales, colour = store))
ggplot2::ggplot(chokubai, ggplot2::aes(factor(month), sales,
colour = store, group = store)) +
# 折れ線を追加
ggplot2::geom_line(linewidth = 1) +
# ポイントを追加
ggplot2::geom_point(size = 3) +
# 軸と凡例のラベルを設定
ggplot2::labs(x = "月", y = "売上高(万円)", colour = "店舗") +
# 凡例を右へ移し、明るめのパレットと書き出しサイズを調整
theme_plus(
legend_pos = "right",
base_font_size = 14,
palette_discrete = "H",
end_discrete = 0.85,
export_width = 9,
export_height = 6)・既定値のままテーマを適用

・凡例を右へ移し、明るめのパレットと書き出しサイズを調整

[連続軸にのみ補助線を追加]:gridlines_plusコマンド
連続量が割り当てられた軸にだけ主目盛りの補助線を引き、補助目盛りの線は消去します。なお、補助線の色や太さはtheme()側ではなく本コマンドで指定します。
| オプション | 意味 | 初期値 |
|---|---|---|
| color | 補助線の色を指定 | “gray90” |
| linewidth | 補助線の太さを指定 | 1.2 |
| linetype | 補助線の種類を”solid”や”dashed”などで指定 | “solid” |
| notx | x方向の補助線を引かないかを論理値で指定 | FALSE |
| noty | y方向の補助線を引かないかを論理値で指定 | FALSE |
| override_legend_alphasize | 凡例の大きさと透明度を本パッケージの既定値で上書きするかを指定 | TRUE |
| enable_coaching | ユニバーサルデザイン上の問題を自動で検査し助言を表示するかを指定 | TRUE |
# 平均気温と売上高の関係をプロット
ggplot2::ggplot(chokubai, ggplot2::aes(temp, sales)) +
# 点を追加
ggplot2::geom_point(size = 2) +
# 軸ラベルを設定
ggplot2::labs(x = "平均気温(度)", y = "売上高(万円)") +
# テーマを適用
theme_plus() +
# xとyの両方が連続量のため、縦横に補助線を追加
gridlines_plus()
# 店舗別の来客数を箱ひげ図でプロット
ggplot2::ggplot(chokubai, ggplot2::aes(store, visitor)) +
# 箱ひげを追加
ggplot2::geom_boxplot() +
# 軸ラベルを設定
ggplot2::labs(x = "店舗", y = "来客数(人)") +
# テーマを適用
theme_plus() +
# xは離散量のため、y方向にのみ細い破線の補助線を追加
gridlines_plus(color = "gray80", linewidth = 0.8, linetype = "dashed")・平均気温と売上高の関係をプロット

・店舗別の来客数を箱ひげ図でプロット

[凡例の代わりに直接ラベルを配置]:direct_labels_plusコマンド
グループごとの点や折れ線に、凡例の代わりとなるラベルをグラフ上へ直接配置します。ラベルの描画にはggrepelが利用されるため、ラベル同士やデータとの重なりが自動で調整されます。なお、本コマンドは公式ヘルプで実験的な機能と位置付けられており、散布図と折れ線のグラフでの利用が想定されています。
| オプション | 意味 | 初期値 |
|---|---|---|
| data | 描画とラベル付けに使うデータフレームを指定 | なし |
| x | x座標となる列名をクォートなしで指定 | なし |
| y | y座標となる列名をクォートなしで指定 | なし |
| group | グループ分けに使う列名をクォートなしで指定 | なし |
| placement | ラベルの配置を”top”、”right”、”bottom”、”left”から指定 | “top” |
| geometry | ラベルを付ける対象を”point”または”line”で指定 | “point” |
| adj_fact | ラベル位置を端へ寄せる量をグループの範囲に対する割合で指定 | 0 |
| key_labels | ラベルの表示内容を関数または文字ベクトルで指定 | NULL |
| facet_vars | 分割描画に使っている変数名を最大2つまで文字ベクトルで指定 | NULL |
| … | ggrepel::geom_label_repel()へ渡す追加の引数を指定 | なし |
# 店舗ごとの月別来客数をプロット
## 修正前のコード ggplot2::ggplot(chokubai, ggplot2::aes(month, visitor, colour = store))
ggplot2::ggplot(chokubai, ggplot2::aes(factor(month), visitor,
colour = store, group = store)) +
# 折れ線を追加
ggplot2::geom_line(linewidth = 1) +
# ポイントを追加
ggplot2::geom_point(size = 3) +
# 折れ線の右端に店舗名のラベルを配置
direct_labels_plus(
data = chokubai,
x = month,
y = visitor,
group = store,
placement = "right",
geometry = "line",
adj_fact = 0) +
# ラベルで判別できるため凡例を非表示
ggplot2::guides(colour = "none") +
# 軸ラベルを設定
ggplot2::labs(x = "月", y = "来客数(人)") +
# テーマを適用
theme_plus()
# 平均気温と売上高の関係を店舗別にプロット
ggplot2::ggplot(chokubai, ggplot2::aes(temp, sales, fill = store)) +
# 点を追加
ggplot2::geom_point(size = 4) +
# 各店舗の点群の上端に短縮名のラベルを配置
direct_labels_plus(
data = chokubai,
x = temp,
y = sales,
group = store,
placement = "top",
geometry = "point",
key_labels = c("みどり直売所" = "みどり",
"あおば直売所" = "あおば",
"ひなた直売所" = "ひなた",
"こもれび直売所" = "こもれび",
"かぜまち直売所" = "かぜまち")) +
# ラベルで判別できるため凡例を非表示
ggplot2::guides(colour = "none") +
# 軸ラベルを設定
ggplot2::labs(x = "平均気温(度)", y = "売上高(万円)") +
# テーマを適用
theme_plus(palette_discrete = "H")・店舗ごとの月別来客数をプロット舗ごとの月別来客数をプロット

・平均気温と売上高の関係を店舗別にプロット

[y軸タイトルを上部へ移動]:yaxis_title_plusコマンド
縦書きになりがちなy軸タイトルを、目盛りラベルの左端に合わせて上部へ水平に配置します。y軸ラベルの売上高(万円)が水平表示になっていることがわかります。
| オプション | 意味 | 初期値 |
|---|---|---|
| location | y軸タイトルの配置を”top”または”bottom”で指定 | “top” |
| nudgeTopLegendDown | 上部の凡例を下へずらすかを論理値で指定 | FALSE |
| nudgeHowMuch | 上部の凡例を下へずらす量をポイントで指定 | 20 |
| override_legend_alphasize | 凡例の大きさと透明度を本パッケージの既定値で上書きするかを指定 | TRUE |
| enable_coaching | ユニバーサルデザイン上の問題を自動で検査し助言を表示するかを指定 | TRUE |
# 月別の合計売上高を集計
gokei <- aggregate(sales ~ month, data = chokubai, FUN = sum)
# 月別の合計売上高を棒グラフで描画
ggplot2::ggplot(gokei, ggplot2::aes(factor(month), sales)) +
# 棒を追加
ggplot2::geom_col(fill = "gray40") +
# 軸ラベルを設定
ggplot2::labs(x = "月", y = "売上高(万円)") +
# テーマを適用
theme_plus() +
# y軸タイトルを上部へ移動
yaxis_title_plus()
[点の重なりを避けて描画]:geom_jitter_plusコマンド
後述のgeom_point_plusコマンドに、点の位置をずらす処理を加えたコマンドです。塗り分けられる独自の点形状をそのまま利用しながら、ggplot2::position_jitter()と同じwidth、height、seedを指定できます。
| オプション | 意味 | 初期値 |
|---|---|---|
| mapping | ggplot2::aes()で作成した審美的属性の対応付けを指定 | NULL |
| data | このレイヤーで表示するデータを指定 | NULL |
| stat | このレイヤーで用いる統計変換を指定 | “identity” |
| position | データの位置調整を指定 | “jitter” |
| … | geom_point_plus()を含む下層のレイヤーへ渡す追加の引数を指定 | なし |
| width | 水平方向に位置をずらす量を指定 | NULL |
| height | 垂直方向に位置をずらす量を指定 | NULL |
| seed | 位置のずれを再現するための乱数の種を指定 | NA |
| na.rm | 欠損値を警告なく除去するかを論理値で指定 | FALSE |
| show.legend | このレイヤーを凡例に含めるかを論理値で指定 | NA |
| inherit.aes | 全体の審美的属性を継承するかを論理値で指定 | TRUE |
# 店舗別の来客数をプロット
ggplot2::ggplot(chokubai, ggplot2::aes(store, visitor)) +
# 点を左右にずらし、平均気温で塗り分けて追加
geom_jitter_plus(
ggplot2::aes(shape = store, fill = temp),
width = 0.15,
seed = 1,
colour = "black",
size = 4
) +
# 軸と凡例のラベルを設定
ggplot2::labs(x = "店舗", y = "来客数(人)",
fill = "平均気温(度)", shape = "店舗") +
# テーマを適用
theme_plus()
[塗り分けできる独自形状で散布図を作成]:geom_point_plusコマンド
ggplot2::geom_point()と同じ感覚で使えて、輪郭と内側を塗り分けられる独自の点形状を利用できます。形状は互いの違いが大きくなるよう設計されているため、色に頼らずにグループを区別できます。
| オプション | 意味 | 初期値 |
|---|---|---|
| mapping | ggplot2::aes()で作成した審美的属性の対応付けを指定 | NULL |
| data | このレイヤーで表示するデータを指定 | NULL |
| stat | このレイヤーで用いる統計変換を指定 | “identity” |
| position | データの位置調整を指定 | “identity” |
| avail_shapes | 標準の形状群に代えて使う独自形状の名前付きリストを指定 | NULL |
| n_shapes | 形状群から使用できる形状の個数を指定 | length(avail_shapes) |
| chosen_shapes | 使用する形状を登録名の文字ベクトルで指定 | NULL |
| legend_title | 形状の凡例のタイトルを指定 | NULL |
| legend_labels | 形状の凡例のラベルを文字ベクトルで指定 | NULL |
| include_shape_legend | 形状の凡例を表示するかを論理値で指定 | TRUE |
| … | このレイヤーのparamsへ渡す追加の引数を指定 | なし |
| na.rm | 欠損値を警告なく除去するかを論理値で指定 | FALSE |
| show.legend | このレイヤーを凡例に含めるかを論理値で指定 | NA |
| inherit.aes | 全体の審美的属性を継承するかを論理値で指定 | TRUE |
| show_shape_scale | 形状スケールの呼び出しを内部で行うかを論理値で指定 | TRUE |
# 平均気温と売上高の関係をプロット
ggplot2::ggplot(chokubai, ggplot2::aes(temp, sales, fill = visitor)) +
# 店舗を形状、来客数を塗りに割り当てて点を追加
geom_point_plus(ggplot2::aes(shape = store), size = 5) +
# 軸と凡例のラベルを設定
ggplot2::labs(x = "平均気温(度)", y = "売上高(万円)",
fill = "来客数(人)", shape = "店舗") +
# テーマを適用
theme_plus()
[利用できる点の形状を確認]:geom_point_plus_shapesコマンド
geom_point_plusコマンドで使用できる形状を一覧を確認できます。形状はggplotplus_shapes_listに名前付きリストとして収録されていて、chosen_shapesへ名前を指定します。
# 利用できる点の形状の名前を確認
names(ggplotplus_shapes_list)実行結果:
[1] "plus" "octagon" "lotus" "oval"
[5] "waffle" "flower" "economy" "squircle"
[9] "sunburst" "circle" "square" "diamond"
[13] "triangle_up" "triangle_down"# 独自形状の一覧を確認
geom_point_plus_shapes()
[目盛りの位置を自動で調整]:scale_continuous_plusコマンド
x、y、colour、fillの連続スケールについて、きりのよい目盛りを選びながら軸の範囲をわずかに広げ、データの両端付近にも目盛りが現れるよう調整します。breaksやlimitsは本コマンドが内部で決めるため、指定しても警告とともに無視されます。
| オプション | 意味 | 初期値 |
|---|---|---|
| scale | 調整するスケールを”x”、”y”、”colour”、”color”、”fill”から指定 | NA |
| … | 対応するggplot2の連続スケールへ渡すnameやlabelsなどを指定 | なし |
| thin.labels | 目盛りラベルを1つおきに空白にするかを論理値で指定 | FALSE |
| pad.labels | ラベルが不足する場合に空白を補う位置を”start”または”end”で指定 | “start” |
| target.breaks | 主目盛りの目標とする個数を指定 | 5 |
| buffer_frac | 両端に目盛りを置くかの判定に使うデータ範囲の割合を指定 | 0.05 |
| split_name | nameに含まれる空白を改行へ置き換えるかを論理値で指定 | FALSE |
# 平均気温と売上高の関係を来客数で塗り分けてプロット
ggplot2::ggplot(chokubai, ggplot2::aes(temp, sales, fill = visitor)) +
# 輪郭のある点を追加
ggplot2::geom_point(shape = 21, size = 3) +
# x軸の目盛りを設定
scale_continuous_plus(scale = "x", name = "平均気温(度)") +
# y軸は目盛りを多めに取り、ラベルを1つおきに空白化
scale_continuous_plus(scale = "y",
name = "売上高(万円)",
target.breaks = 8,
thin.labels = TRUE) +
# 塗りのスケールを設定し、タイトルの空白位置で改行
scale_continuous_plus(scale = "fill",
name = "来客数 (人)",
split_name = TRUE) +
# テーマを適用
theme_plus()
[注目するグループのみを強調]:scale_focus_plusコマンド
指定したグループにのみ色を割り当て、それ以外を灰色にする色スケールを作成します。全体の文脈を残したまま注目してほしい系列を示せるため、読み手が要点を見つけやすくなります。
| オプション | 意味 | 初期値 |
|---|---|---|
| aes | 対象の審美的属性を”color”、”colour”、”fill”から指定 | なし |
| group_var | その属性に割り当てたグループ変数のベクトルを指定 | なし |
| focal_groups | 強調するグループの値を文字ベクトルで指定 | なし |
| diff_nonfocal | 強調しないグループに異なる色を割り当てるかを論理値で指定 | FALSE |
| diff_focal | 強調するグループに異なる色を割り当てるかを論理値で指定 | TRUE |
| gray_start | 強調しないグループに使う灰色の範囲の始点を0から1で指定 | 0.35 |
| gray_end | 強調しないグループに使う灰色の範囲の終点を0から1で指定 | 0.65 |
| focal_start | 強調するグループに使うviridisパレットの範囲の始点を0から1で指定 | 0.75 |
| focal_end | 強調するグループに使うviridisパレットの範囲の終点を0から1で指定 | 0.25 |
| custom_focal | 強調するグループに使う任意の色を指定 | NULL |
| custom_nonfocal | 強調しないグループに使う任意の色を指定 | NULL |
| … | ggplot2の手動スケールへ渡すnameやlabelsなどを指定 | なし |
# 店舗ごとの月別来客数をプロット
## 修正前のコード ggplot2::ggplot(chokubai, ggplot2::aes(month, visitor,
## colour = store, group = store))
ggplot2::ggplot(chokubai, ggplot2::aes(factor(month), visitor, fill = store,
colour = store, group = store)) +
# 折れ線を追加
ggplot2::geom_line(linewidth = 2) +
# ポイントを追加
ggplot2::geom_point(size = 4, shape = 21) +
# colourへの適用
scale_focus_plus(aes = "colour",
group_var = chokubai$store,
focal_groups = c("ひなた直売所", "みどり直売所"),
diff_focal = FALSE,
custom_focal = "red",
custom_nonfocal = "gray70") +
# fillへの適用
scale_focus_plus(aes = "fill",
group_var = chokubai$store,
focal_groups = c("ひなた直売所", "みどり直売所"),
) +
# 軸と凡例のラベルを設定(colour と fill のタイトルを完全に一致させる)
ggplot2::labs(x = "月", y = "来客数(人)", colour = "店舗", fill = "店舗") +
# テーマを適用
theme_plus()
# 店舗ごとの年間売上高を棒グラフでプロット
ggplot2::ggplot(nenkan, ggplot2::aes(store, sales, fill = store)) +
# 棒グラフ
ggplot2::geom_col() +
# 強調しない店舗にも濃淡を付け、灰色の範囲を広げて表示
scale_focus_plus(aes = "fill",
group_var = nenkan$store,
focal_groups = c("みどり直売所", "ひなた直売所"),
diff_nonfocal = TRUE,
gray_start = 0.55,
gray_end = 0.85,
name = "店舗") +
# 軸ラベルを設定
ggplot2::labs(x = NULL, y = "年間売上高(万円)") +
# テーマを適用
theme_plus()・店舗ごとの月別来客数をプロット

・店舗ごとの年間売上高を棒グラフでプロット

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