からっぽのしょこ

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

ggtext::geom_richtext関数によるラベル付け

はじめに

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

【他の関数】

www.anarchive-beta.com

www.anarchive-beta.com

【他の内容】

www.anarchive-beta.com

【この記事の内容】

ggtext::geom_richtext関数

 ggtextパッケージのラベル付け関数geom_richtext()の引数を確認します。共通する引数については説明を省略するので、「ggplot2::geom_label関数」も参照してください。
 この記事での作図コードやデータフレームは、あくまで参考図を作るためのものです。必要な部分を汲み取って利用してください。

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

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

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

デフォルト

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

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

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

デフォルトの設定

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

 fill, label.color引数をNAにすると、文字列のみを描画します。

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

テキストのみの設定

 {ggplot2}では、文字列のみの場合はgeom_text()を使います。{ggtext}では、どちらもgeom_richtext()で行えます。

label引数

 文字列を描画するlabel引数について、{ggplot2}との違いを簡単に確認します。

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

# ラベルテキストを指定
label_df <- tidyr::tibble(
  str = c("label text", "label\ntext", "label<br>text"), 
  label = paste0('label = "', stringr::str_replace(str, pattern = "\n", replacement = "\\\\n"), '"'), 
  y = dplyr::row_number(label)
)
label_df
## # A tibble: 3 × 3
##   str             label                           y
##   <chr>           <chr>                       <int>
## 1 "label text"    "label = \"label text\""        1
## 2 "label\ntext"   "label = \"label\\ntext\""      2
## 3 "label<br>text" "label = \"label<br>text\""     3

 (比較用の図のためにアレコレしています。)

# ラベルテキストを確認
ggplot(data = label_df, mapping = aes(y = y)) + 
  ggplot2::geom_text(mapping = aes(label = label, x = 0)) + 
  ggplot2::geom_label(mapping = aes(label = str, x = 1)) + 
  ggtext::geom_richtext(mapping = aes(label = str, x = 2)) + 
  scale_y_reverse() + # y軸を判定
  scale_x_continuous(breaks = 0:2, 
                     labels = c("argment", "ggplot2::geom_label()", "ggtext::geom_richtext()"), 
                     limits = c(-0.5, 2.5)) + # x軸目盛ラベルを指定
  theme(axis.title = element_blank(), 
        axis.text.y = element_blank(), 
        axis.ticks.y = element_blank(), 
        panel.grid.minor.y = element_blank()) # 軸線を非表示化


label引数

 {ggplot2}では、メタ文字(?)が使えました。{ggtext}では、htmlが使えます。

text.color引数・label.color引数

 color引数は文字列と枠線、text.color引数は文字列、label.color引数は枠線の色を設定できます。

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

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

# 色を指定
ggplot(data = point_df, mapping = aes(x = x)) + 
  ggtext::geom_richtext(y = 0, label = 'color = "red", fill = "yellow"', 
                        color = "red", fill = "yellow", 
                        label.padding = unit(0.8, units = "lines"), label.size = 2) + 
  ggtext::geom_richtext(y = 1, label = 'color = "red", fill = "yellow", label.color = "wheat1"', 
                        color = "red", fill = "yellow", label.color = "wheat1", 
                        label.padding = unit(0.8, units = "lines"), label.size = 2) + 
  ggtext::geom_richtext(y = 2, label = 'text.color = "red", label.color = "wheat1", fill = "yellow"', 
                        text.color = "red", label.color = "wheat1", fill = "yellow", 
                        label.padding = unit(0.8, units = "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, 2.5)) + # 表示範囲
  labs(title = "ggtext::geom_richtext()")


text.color引数とlabel.color引数

 color引数とlabel.color引数を指定すると、label.color引数の設定が優先されます。

label.padding引数

 文字列と枠線の間の余白をunit()を使ってlabel.padding引数で設定できます。{ggplot2}では上下左右で共通の設定でしたが、{ggtext}ではそれぞれ指定できます。ただし、指定する順序は上右下左(上から時計回り)です。

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

# 4方向の値を指定
pad_df <- tidyr::expand_grid(
  x = seq(from = -2, to = 2, by = 0.5), 
  y = seq(from = -2, to = 2, by = 0.5)
) |> 
  dplyr::mutate(
    top = dplyr::if_else(y > 0, true = y, false = 0), 
    right = dplyr::if_else(x > 0, true = x, false = 0), 
    bottom = dplyr::if_else(y < 0, true = -y, false = 0), 
    left = dplyr::if_else(x < 0, true = -x, false = 0), 
    label = paste0(
      "c(", 
      stringr::str_pad(top, width = 3, side = "left"), ", ", 
      stringr::str_pad(right, width = 3, side = "left"), ", ", 
      stringr::str_pad(bottom, width = 3, side = "left"), ", ", 
      stringr::str_pad(left, width = 3, side = "left"), 
      ")"
    ) # 確認用ラベル
  )
pad_df
## # A tibble: 81 × 7
##        x     y   top right bottom  left label                
##    <dbl> <dbl> <dbl> <dbl>  <dbl> <dbl> <chr>                
##  1  -2    -2     0       0    2     2   c(  0,   0,   2,   2)
##  2  -2    -1.5   0       0    1.5   2   c(  0,   0, 1.5,   2)
##  3  -2    -1     0       0    1     2   c(  0,   0,   1,   2)
##  4  -2    -0.5   0       0    0.5   2   c(  0,   0, 0.5,   2)
##  5  -2     0     0       0    0     2   c(  0,   0,   0,   2)
##  6  -2     0.5   0.5     0    0     2   c(0.5,   0,   0,   2)
##  7  -2     1     1       0    0     2   c(  1,   0,   0,   2)
##  8  -2     1.5   1.5     0    0     2   c(1.5,   0,   0,   2)
##  9  -2     2     2       0    0     2   c(  2,   0,   0,   2)
## 10  -1.5  -2     0       0    2     1.5 c(  0,   0,   2, 1.5)
## # … with 71 more rows

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

# 文字列と枠線の間を確認
g <- ggplot() + 
  theme(axis.title = element_blank(), 
        axis.text = element_blank(), 
        axis.ticks = element_blank()) + # 軸線を非表示化
  lims(x = c(min(pad_df[["x"]])-0.5, max(pad_df[["x"]])+0.5), 
       y = c(min(pad_df[["y"]])-0.5, max(pad_df[["y"]])+0.5)) + # 表示範囲
  labs(title = 'ggtext::geom_richtext(label.padding = unit(c(top, right, bottom, left), "lines"))')
for(i in 1:nrow(pad_df)) {
  # 値ごとにラベルを重ねて描画
  g <- g + 
    ggtext::geom_richtext(data = pad_df[i, ], mapping = aes(x = x, y = y, label = label), 
                          label.padding = unit(as.numeric(pad_df[i, c("top", "right", "bottom", "left")]), units = "lines"))
}
g

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


label.padding引数

 値が大きいほど、指定した方向の余白が広くなり枠が大きくなります。
 デフォルトはunit(c(0.25, 0.25, 0.25, 0.25), "lines")です。

label.margin引数

 枠線の外側(上下左右の4方向)の余白をunit()を使ってlabel.padding引数で設定できます。

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

# 4方向の値を指定
margin_df <- tidyr::expand_grid(
  margin_x = seq(from = -40, to = 40, by = 20), 
  margin_y = seq(from = -40, to = 40, by = 10)
) |> 
  dplyr::mutate(
    top = dplyr::if_else(margin_y > 0, true = margin_y, false = 0), 
    right = dplyr::if_else(margin_x > 0, true = margin_x, false = 0), 
    bottom = dplyr::if_else(margin_y < 0, true = -margin_y, false = 0), 
    left = dplyr::if_else(margin_x < 0, true = -margin_x, false = 0), 
    label = paste0(
      "c(", 
      stringr::str_pad(top, width = 3, side = "left"), ", ", 
      stringr::str_pad(right, width = 3, side = "left"), ", ", 
      stringr::str_pad(bottom, width = 3, side = "left"), ", ", 
      stringr::str_pad(left, width = 3, side = "left"), 
      ")"
    ) # 確認用ラベル
  )
margin_df
## # A tibble: 45 × 7
##    margin_x margin_y   top right bottom  left label                
##       <dbl>    <dbl> <dbl> <dbl>  <dbl> <dbl> <chr>                
##  1      -40      -40     0     0     40    40 c(  0,   0,  40,  40)
##  2      -40      -30     0     0     30    40 c(  0,   0,  30,  40)
##  3      -40      -20     0     0     20    40 c(  0,   0,  20,  40)
##  4      -40      -10     0     0     10    40 c(  0,   0,  10,  40)
##  5      -40        0     0     0      0    40 c(  0,   0,   0,  40)
##  6      -40       10    10     0      0    40 c( 10,   0,   0,  40)
##  7      -40       20    20     0      0    40 c( 20,   0,   0,  40)
##  8      -40       30    30     0      0    40 c( 30,   0,   0,  40)
##  9      -40       40    40     0      0    40 c( 40,   0,   0,  40)
## 10      -20      -40     0     0     40    20 c(  0,   0,  40,  20)
## # … with 35 more rows

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

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

# ラベル外側の余白を確認
g <- ggplot() + 
  lims(x = c(-1, 1), y = c(-1, 1)) + # 表示範囲
  #lims(x = c(-10, 10), y = c(-10, 10)) + # 表示範囲
  labs(title = 'ggtext::geom_richtext(label.margin = unit(c(top, right, bottom, left), "lines"))')
for(i in 1:nrow(margin_df)) {
  # 値ごとにラベルを重ねて描画
  g <- g + 
    ggtext::geom_richtext(data = margin_df[i, ], mapping = aes(label = label), 
                          x = 0, y = 0, hjust = 0.5, vjust = 0.5, 
                          label.margin = unit(as.numeric(margin_df[i, c("top", "right", "bottom", "left")]), units = "lines"))
}
g <- g + 
  geom_point(data = dummy_df, x = 0, y = 0, color = "red", shape = 13, size = 13) # プロット位置を確認
g


label.margin引数

 プロット位置を赤色の印で示しています。この図の全てのラベルは、同じ位置を基準にプロットされています。
 値が大きいほど、指定した方向の余白が広くなるので、プロット位置から離れていきます。ただし、相対的な配置位置なので軸の値は影響しません。
 デフォルトは余白なしunit(c(0, 0, 0, 0), "lines")です。

 この記事では、ggtextパッケージのgeom_richtext()を解説しました。次の記事では、geom_textbox()を解説します。

参考

おわりに

 色々なおまけで生えた記事です。もう1つ続きます。

【次の内容】

www.anarchive-beta.com