からっぽのしょこ

読んだら書く!書いたら読む!同じ事は二度調べ(たく)ない

ggplot2::geom_label関数によるラベル付け

はじめに

 この記事は「R Advent Calendar 2022」の8日目の記事です。

 R言語でグラフに文字列を書く込むための関数を確認していきます。
 この記事では、ggplot2パッケージのgeom_lable()を扱います。

【他の関数】

www.anarchive-beta.com

www.anarchive-beta.com

【他の内容】

www.anarchive-beta.com

【この記事の内容】

ggplot2::geom_label関数

 ggplot2パッケージのラベル付け関数geom_lable()の引数を確認します。より細かく設定したい場合は「ggtext::geom_richtext関数」や「ggtext::geom_textbox関数」も参照してください。
 この記事での作図コードやデータフレームは、あくまで参考図を作るためのものです。必要な部分を汲み取って利用してください。

 利用するパッケージを読み込みます。

# 利用パッケージ
library(tidyverse)

 この記事では、基本的にパッケージ名::関数名()の記法を使うので、パッケージを読み込む必要はありません。ただし、作図コードがごちゃごちゃしないようにパッケージ名を省略しているため、ggplot2は読み込む必要があります。
 また、ネイティブパイプ演算子|>を使っています。magrittrパッケージのパイプ演算子%>%に置き換えても処理できますが、その場合はmagrittrも読み込む必要があります。

デフォルト

 まずは、デフォルトの設定で描画してみます。

# ダミーのデータフレームを作成
dummy_df <- tidyr::tibble(v = 0)

# デフォルトのラベルを確認
ggplot(data = dummy_df) + 
  geom_label(x = 0, y = 0, label = "label text") + # ラベル
  coord_equal() + # アスペクト比
  lims(x = c(-1, 1), y = c(-1, 1)) + # 表示範囲
  labs(title = "ggplot2::geom_label()")

デフォルトの設定

 プロット位置(x, y引数)は、geom_label()の引数として(aes()の外で)指定できますが、何かしらのデータフレームを渡しておく必要があります。(1データであってもデータフレームに値を持たせて描画した方がいいのでしょう。)

hjust引数・vjust引数

 プロット位置(x, y引数)に対するラベルの横方向の配置位置をhjust引数、縦方向の配置位置をvjust引数で設定できます。

作図コード(クリックで展開)

# 配置位置を指定
just_df <- tidyr::expand_grid(
  h = c(0, 0.5, 1), 
  v = c(0, 0.5, 1)
) |> # 格子点を作成
  dplyr::mutate(
    x = h, 
    y = v, 
    label = paste0(
      "hjust = ", stringr::str_pad(h, width = 3, side = "right"), "\n", 
      "vjust = ", stringr::str_pad(v, width = 3, side = "right")
    ) # 確認用ラベル
  )
just_df
## # A tibble: 9 × 5
##       h     v     x     y label                     
##   <dbl> <dbl> <dbl> <dbl> <chr>                     
## 1   0     0     0     0   "hjust = 0  \nvjust = 0  "
## 2   0     0.5   0     0.5 "hjust = 0  \nvjust = 0.5"
## 3   0     1     0     1   "hjust = 0  \nvjust = 1  "
## 4   0.5   0     0.5   0   "hjust = 0.5\nvjust = 0  "
## 5   0.5   0.5   0.5   0.5 "hjust = 0.5\nvjust = 0.5"
## 6   0.5   1     0.5   1   "hjust = 0.5\nvjust = 1  "
## 7   1     0     1     0   "hjust = 1  \nvjust = 0  "
## 8   1     0.5   1     0.5 "hjust = 1  \nvjust = 0.5"
## 9   1     1     1     1   "hjust = 1  \nvjust = 1  "

 (ラベル内で(極力)イコールが揃うように半角スペースで調整しようとしています。)ラベル内での中央揃えなどをしたい場合は「ggtext::geom_textbox関数」を参照してください。

 aes()の引数として、データごとに指定できます。

# 配置位置を確認
ggplot(data = just_df, mapping = aes(x = x, y = y)) + 
  geom_label(mapping = aes(label = label, hjust = h, vjust = v)) + 
  geom_point(color = "red", size = 3) + # プロット位置を確認
  coord_equal() + # アスペクト比
  labs(title = "ggplot2::geom_label()")


hjust引数とvjust引数

 プロット位置を赤色の点で示しています。
 hjust = 0なら左揃え、hjust = 1なら右揃え、vjust = 0なら下揃え、vjust = 1なら上揃えになります。また、それぞれ0.5なら中央揃えになります。それ以外の値も指定できます。
 デフォルトはそれぞれ0.5です。

size引数

 文字列と枠の大きさをsize引数で設定できます。

作図コード(クリックで展開)

# ラベルのサイズを指定
size_df <- tibble::tibble(
  s = seq(from = 0.1, to = 1.5, by = 0.1), 
  y = dplyr::row_number(s), 
  label = paste0("size = ", stringr::str_pad(round(s, digits = 1), width = 3, side = "right")) # 確認用ラベル
)
size_df
## # A tibble: 15 × 3
##        s     y label       
##    <dbl> <int> <chr>       
##  1   0.1     1 "size = 0.1"
##  2   0.2     2 "size = 0.2"
##  3   0.3     3 "size = 0.3"
##  4   0.4     4 "size = 0.4"
##  5   0.5     5 "size = 0.5"
##  6   0.6     6 "size = 0.6"
##  7   0.7     7 "size = 0.7"
##  8   0.8     8 "size = 0.8"
##  9   0.9     9 "size = 0.9"
## 10   1      10 "size = 1  "
## 11   1.1    11 "size = 1.1"
## 12   1.2    12 "size = 1.2"
## 13   1.3    13 "size = 1.3"
## 14   1.4    14 "size = 1.4"
## 15   1.5    15 "size = 1.5"

 aes()の引数として、データごとに指定できます。

# ラベルのサイズを確認
ggplot(data = size_df, mapping = aes(y = y, label = label, size = s)) + 
  geom_label(x = 1, hjust = 0, show.legend = FALSE) + # 左揃え
  geom_label(x = 2, hjust = 0.5, show.legend = FALSE) + # 中央揃え
  geom_label(x = 3, hjust = 1, show.legend = FALSE) + # 右揃え
  theme(axis.title = element_blank(), 
        axis.text.y = element_blank(), 
        axis.ticks.y = element_blank()) + # 軸線を非表示化
  scale_x_continuous(breaks = 1:3, 
                     labels = c("hjust = 0", "hjust = 0.5", "hjust = 1"), 
                     limits = c(0.5, 3.5)) + 
  labs(title = "ggplot2::geom_label()")


size引数

 (デフォルトはいくつでしょうか?)
 枠サイズだけを調整する場合はlable.padding引数を使います。

label.size引数

 枠線の太さをlabel.sizeで設定できます。

作図コード(クリックで展開)

# 枠線の太さを指定
size_df <- tibble::tibble(
  s = seq(from = 0.1, to = 1.5, by = 0.1), 
  x = 0,
  y = dplyr::row_number(s) - 1, 
  label = paste0("label.size = ", stringr::str_pad(round(s, digits = 1), width = 3, side = "right")) # 確認用ラベル
)
size_df
## # A tibble: 15 × 4
##        s     x     y label             
##    <dbl> <dbl> <dbl> <chr>             
##  1   0.1     0     0 "label.size = 0.1"
##  2   0.2     0     1 "label.size = 0.2"
##  3   0.3     0     2 "label.size = 0.3"
##  4   0.4     0     3 "label.size = 0.4"
##  5   0.5     0     4 "label.size = 0.5"
##  6   0.6     0     5 "label.size = 0.6"
##  7   0.7     0     6 "label.size = 0.7"
##  8   0.8     0     7 "label.size = 0.8"
##  9   0.9     0     8 "label.size = 0.9"
## 10   1       0     9 "label.size = 1  "
## 11   1.1     0    10 "label.size = 1.1"
## 12   1.2     0    11 "label.size = 1.2"
## 13   1.3     0    12 "label.size = 1.3"
## 14   1.4     0    13 "label.size = 1.4"
## 15   1.5     0    14 "label.size = 1.5"

 データごとに(aes()の中で)設定できません。

# 枠線の太さを確認
g <- ggplot() + 
  theme(axis.title = element_blank(), 
        axis.text = element_blank(), 
        axis.ticks = element_blank()) + # 軸線を非表示化
  lims(x = c(-0.5, 0.5)) + # 表示範囲
  labs(title = "ggplot2::geom_label()")
for(i in 1:nrow(size_df)) {
  # 値ごとにラベルを重ねて描画
  g <- g + 
    geom_label(data = size_df[i, ], mapping = aes(x = x, y = y, label = label), 
               label.size = size_df[["s"]][i])
}
g

 (label.***引数はデータごとに指定できないため、for()を使って1データずつ設定を変更して描画しています。)


label.size引数

 値が大きいほどラベルが大きくなります。
 デフォルトは0.25です。

label.padding引数

 文字列と枠線の間の余白をunit()を使ってlabel.padding引数で設定できます。

作図コード(クリックで展開)

# 文字列と枠線の間を指定
pad_df <- tibble::tibble(
  pad = seq(from = 0, to = 1.5, by = 0.1), 
  y = dplyr::row_number(pad), 
  label = paste0(
    "label.padding = unit(", 
    stringr::str_pad(round(pad, digits = 1), width = 3, side = "right"), 
    ', "lines")'
  ) # 確認用ラベル
)
pad_df
## # A tibble: 16 × 3
##      pad     y label                                 
##    <dbl> <int> <chr>                                 
##  1   0       1 "label.padding = unit(0  , \"lines\")"
##  2   0.1     2 "label.padding = unit(0.1, \"lines\")"
##  3   0.2     3 "label.padding = unit(0.2, \"lines\")"
##  4   0.3     4 "label.padding = unit(0.3, \"lines\")"
##  5   0.4     5 "label.padding = unit(0.4, \"lines\")"
##  6   0.5     6 "label.padding = unit(0.5, \"lines\")"
##  7   0.6     7 "label.padding = unit(0.6, \"lines\")"
##  8   0.7     8 "label.padding = unit(0.7, \"lines\")"
##  9   0.8     9 "label.padding = unit(0.8, \"lines\")"
## 10   0.9    10 "label.padding = unit(0.9, \"lines\")"
## 11   1      11 "label.padding = unit(1  , \"lines\")"
## 12   1.1    12 "label.padding = unit(1.1, \"lines\")"
## 13   1.2    13 "label.padding = unit(1.2, \"lines\")"
## 14   1.3    14 "label.padding = unit(1.3, \"lines\")"
## 15   1.4    15 "label.padding = unit(1.4, \"lines\")"
## 16   1.5    16 "label.padding = unit(1.5, \"lines\")"

 データごとに(aes()の中で)設定できません。

# 文字列と枠線の間を確認
g <- ggplot() + 
  theme(axis.title = element_blank(), 
        axis.text.y = element_blank(), 
        axis.ticks.y = element_blank()) + # 軸線を非表示化
  scale_x_continuous(breaks = 1:3, 
                     labels = c("hjust = 0", "hjust = 0.5", "hjust = 1"), 
                     limits = c(0.5, 3.5)) + 
  labs(title = "ggplot2::geom_label()")
for(i in 1:nrow(pad_df)) {
  # 値ごとにラベルを重ねて描画
  g <- g + 
    geom_label(data = pad_df[i, ], mapping = aes(y = y, label = label), 
               x = 1, hjust = 0, 
               label.padding = unit(pad_df[["pad"]][i], units = "lines")) + # 左揃え
    geom_label(data = pad_df[i, ], mapping = aes(y = y, label = label), 
               x = 2, hjust = 0.5, 
               label.padding = unit(pad_df[["pad"]][i], units = "lines")) + # 中央揃え
    geom_label(data = pad_df[i, ], mapping = aes(y = y, label = label), 
               x = 3, hjust = 1, 
               label.padding = unit(pad_df[["pad"]][i], units = "lines")) # 右揃え
}
g


label.padding引数

 デフォルトはunit(0.25, "lines")です。"lines"以外も指定できます。
 値が大きいほど、余白が広くなり枠が大きくなります。
 上下左右で別のサイズを指定したい場合は「ggtext::geom_richtext関数」を参照してください。

label.r引数

 四隅の丸みをunit()を使ってlabel.r引数で設定できます。

作図コード(クリックで展開)

# 角の半径を指定
r_lines_df <- tibble::tibble(
  r = seq(from = 0, to = 2, by = 0.1), 
  y = dplyr::row_number(r), 
  label = paste0(
    "label.r = unit(", 
    stringr::str_pad(round(r, digits = 1), width = 3, side = "right"), 
    ', "lines")'
  )
)
r_points_df <- tibble::tibble(
  r = seq(from = 0, to = 20, by = 1), 
  y = dplyr::row_number(r), 
  label = paste0(
    "label.r = unit(", 
    stringr::str_pad(round(r, digits = 1), width = 3, side = "right"), 
    ', "points")'
  )
)
r_lines_df; r_points_df
## # A tibble: 21 × 3
##        r     y label                           
##    <dbl> <int> <chr>                           
##  1   0       1 "label.r = unit(0  , \"lines\")"
##  2   0.1     2 "label.r = unit(0.1, \"lines\")"
##  3   0.2     3 "label.r = unit(0.2, \"lines\")"
##  4   0.3     4 "label.r = unit(0.3, \"lines\")"
##  5   0.4     5 "label.r = unit(0.4, \"lines\")"
##  6   0.5     6 "label.r = unit(0.5, \"lines\")"
##  7   0.6     7 "label.r = unit(0.6, \"lines\")"
##  8   0.7     8 "label.r = unit(0.7, \"lines\")"
##  9   0.8     9 "label.r = unit(0.8, \"lines\")"
## 10   0.9    10 "label.r = unit(0.9, \"lines\")"
## # … with 11 more rows
## # A tibble: 21 × 3
##        r     y label                            
##    <dbl> <int> <chr>                            
##  1     0     1 "label.r = unit(0  , \"points\")"
##  2     1     2 "label.r = unit(1  , \"points\")"
##  3     2     3 "label.r = unit(2  , \"points\")"
##  4     3     4 "label.r = unit(3  , \"points\")"
##  5     4     5 "label.r = unit(4  , \"points\")"
##  6     5     6 "label.r = unit(5  , \"points\")"
##  7     6     7 "label.r = unit(6  , \"points\")"
##  8     7     8 "label.r = unit(7  , \"points\")"
##  9     8     9 "label.r = unit(8  , \"points\")"
## 10     9    10 "label.r = unit(9  , \"points\")"
## # … with 11 more rows

 データごとに(aes()の中で)設定できません。

# 角の半径を確認
g <- ggplot() + 
  theme(axis.title = element_blank(), 
        axis.text = element_blank(), 
        axis.ticks = element_blank()) + # 軸線を非表示化
  lims(x = c(0.5, 2.5)) + # 
  labs(title = "ggplot2::geom_label()")
for(i in 1:nrow(r_lines_df)) {
  # 値ごとにラベルを重ねて描画
  g <- g + 
    geom_label(data = r_lines_df[i, ], mapping = aes(y = y, label = label), x = 1, 
               label.r = unit(r_lines_df[["r"]][i], units = "lines"), label.padding = unit(10, units = "points")) + 
    geom_label(data = r_points_df[i, ], mapping = aes(y = y, label = label), x = 2, 
               label.r = unit(r_points_df[["r"]][i], units = "points"), label.padding = unit(10, units = "points"))
}
g


label.r引数

 0だと長方形になり、値が大きくなると丸みを帯びますが、大きすぎると意図しない形になります。
 デフォルトはunit(0.15, "lines")です。

color引数・fill引数

 color引数で文字列と枠線の色、fill引数で枠内の色を設定できます。文字列と枠線に別の色を指定したい場合は「ggtext::geom_richtext関数」を参照してください。

 まずは、それぞれ1つの色を指定します。

作図コード(クリックで展開)

# プロット位置を指定
point_df <- tidyr::tibble(x = 0, y = 0)

# 色を指定
ggplot() + 
  geom_label(data = point_df, mapping = aes(x = x, y = y), 
             label = 'fill = "yellow", color = "red"', 
             fill = "yellow", color = "red", 
             label.padding = unit(0.8, "lines"), label.size = 2) + 
  labs(title = "ggplot2::geom_label()")


color引数とfill引数

 geom_label()の引数として(aes()の外で)指定します。

 続いて、カテゴリデータに対して、データごとに色を設定することを考えます。

作図コード(クリックで展開)

# 線と塗りつぶしの色を指定
color_df <- tibble::tibble(
  x = 0, 
  y = 1:3, 
  color = c("blue", "yellow", "green"), 
  fill = c("red", "gold", "white"), 
  label = paste0(
    "color = ", stringr::str_pad(color, width = 6, side = "right"), "\n", 
    "    fill = ", stringr::str_pad(fill, width = 6, side = "right")
  ) # 確認用ラベル
)
color_df
## # A tibble: 3 × 5
##       x     y color  fill  label                              
##   <dbl> <int> <chr>  <chr> <chr>                              
## 1     0     1 blue   red   "color = blue  \n    fill = red   "
## 2     0     2 yellow gold  "color = yellow\n    fill = gold  "
## 3     0     3 green  white "color = green \n    fill = white "

 データ(行)ごとに指定したい色名やカラーコードを持たせておき、aes()の引数に列を指定してみます。

# ラベルの色を確認:(失敗)
ggplot() + 
  geom_label(data = color_df, mapping = aes(x = x, y = y, label = label, color = color, fill = fill), 
             size = 5, label.padding = unit(1, "lines"), label.size = 2) + 
  theme(axis.title = element_blank(), 
        axis.text = element_blank(), 
        axis.ticks = element_blank()) + # 軸線を非表示化
  lims(x = c(-0.5, 0.5), y = c(0.5, 3.5)) + # 表示範囲
  labs(title = "ggplot2::geom_label()")

color引数とfill引数

 指定した列の文字列ごとにカテゴリデータとして認識され、自動で色付けされています。
 また、アルファベット順で処理されています。カテゴリに特定の順序を持たせる場合は、因子型に変換してレベルを設定します。

 (color, fill列をカテゴリとして、)カテゴリごとに色を設定します。

# ラベルの色を確認
ggplot() + 
  geom_label(data = color_df, mapping = aes(x = x, y = y, label = label, color = color, fill = fill), 
             size = 5, label.padding = unit(1, "lines"), label.size = 2) + 
  scale_color_manual(breaks = unique(color_df[["color"]]), 
                     values = c("blue", "yellow", "green")) + # 線の色
  scale_fill_manual(breaks = unique(color_df[["fill"]]), 
                    values = c("red", "gold", "white")) + # 塗りつぶし色
  theme(axis.title = element_blank(), 
        axis.text = element_blank(), 
        axis.ticks = element_blank()) + # 軸線を非表示化
  lims(x = c(-0.5, 0.5), y = c(0.5, 3.5)) + # 表示範囲
  labs(title = "ggplot2::geom_label()")

 scale_color_manual()scale_fill_manual()でカテゴリごとに色を指定できます。breaks引数に(color, fill引数に指定された列に含まれる)カテゴリ(文字列)、values引数に(カテゴリごとに設定したい)色(色名やカラーコード)を指定します。カテゴリデータが色名である必要はありません(上手くいかないことを示したかっただけです)。


color引数とfill引数


 次は、連続値のデータに対して色付けをします。

作図コード(クリックで展開)

# 塗りつぶし用の値を指定
fill_df <- tidyr::expand_grid(
  x = -5:5, 
  y = -5:5
) |> # 格子点を作成
  dplyr::mutate(
    z = x + y, 
    label = paste0(
      "fill = ", stringr::str_pad(z, width = 2, side = "right")
    ) # 確認用ラベル
  )
fill_df
## # A tibble: 121 × 4
##        x     y     z label     
##    <int> <int> <int> <chr>     
##  1    -5    -5   -10 fill = -10
##  2    -5    -4    -9 fill = -9 
##  3    -5    -3    -8 fill = -8 
##  4    -5    -2    -7 fill = -7 
##  5    -5    -1    -6 fill = -6 
##  6    -5     0    -5 fill = -5 
##  7    -5     1    -4 fill = -4 
##  8    -5     2    -3 fill = -3 
##  9    -5     3    -2 fill = -2 
## 10    -5     4    -1 fill = -1 
## # … with 111 more rows

 fill引数に連続値の列を指定します。

# 塗りつぶし色を確認
ggplot() + 
  geom_label(data = fill_df, mapping = aes(x = x, y = y, label = label, fill = z), 
             color = "white", label.padding = unit(0.8, "lines")) + 
  coord_equal() + # アスペクト比
  labs(title = "geom_label()", fill = "z=x+y")


fill引数

 fill引数に指定された値に応じて濃淡が付きます。
 color引数の場合も同様です。

 この記事では、ggplot2パッケージのgeom_label()を解説しました。次の記事では、より高機能にラベル付けができるggtextパッケージのgeom_richtext()を解説します。

 Enjoy!

参考

おわりに

 3年目のRアドカレ参加です。もうアドカレの季節なのか、、、一昨年に1つ初投稿して昨年2つ投稿しました。この場合、今年はいくつ投稿すべきでしょうか。3つ?4つ?

 別の記事(Rアドカレ10日目の予定)で{ggtext}geom_textbox()を使うのでその記事の中で解説するために少し調べてみたところ、なぜか3つ記事が生えることになりました。というわけで続きます。

 その前にこの曲を聴いてEnjoy!しましょう。


【次の内容】

www.anarchive-beta.com