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

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

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”
notxx方向の補助線を引かないかを論理値で指定FALSE
notyy方向の補助線を引かないかを論理値で指定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描画とラベル付けに使うデータフレームを指定なし
xx座標となる列名をクォートなしで指定なし
yy座標となる列名をクォートなしで指定なし
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軸ラベルの売上高(万円)が水平表示になっていることがわかります。

オプション意味初期値
locationy軸タイトルの配置を”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を指定できます。

オプション意味初期値
mappingggplot2::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()と同じ感覚で使えて、輪郭と内側を塗り分けられる独自の点形状を利用できます。形状は互いの違いが大きくなるよう設計されているため、色に頼らずにグループを区別できます。

オプション意味初期値
mappingggplot2::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_namenameに含まれる空白を改行へ置き換えるかを論理値で指定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()

・店舗ごとの月別来客数をプロット

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


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

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