戯言日記

Rの話だと思ったら唐突にサバゲーが混じってくる何か。

gtパッケージの表を便利にするための小技

この記事はR言語 Advent Calendar 2023の20日目の記事です。
ギリギリ日付跨いだことについては見なかったことにしてください。

qiita.com

gtパッケージとは

適当なデータをgt::gt()に放り込むだけで、簡単にいい感じの表として出力できるパッケージ。
見た目に関してもかなり詳細に調整できるので論文用の表作成などにも十分使える。
個人的にはExcelに頼らずに済む点で非常に有用。

pacman::p_load(tidyverse, gt)

iris |> 
  reframe(across(where(is.numeric), mean), .by=Species) |> 
  gt()

もっと詳しく知りたい方はこちらが非常に参考になる。

qiita.com


今回のお話

とにかく便利なgtパッケージだが、

  1. セルの文章を改行したい
  2. 特定のセルにハイパーリンクをつけたい

をやろうとした際に沼ってしまった。
具体的にはこんな感じのデータを想定している。

pacman::p_load(tidyverse, gt, tidyRSS)

# R Advent Calendar 2023のRSSからデータを貰ってきて表にする
# なお分量が多いので5行だけ引っ張ってくる
advent <- tidyRSS::tidyfeed("https://qiita.com/advent-calendar/2023/rlang/feed")
colnames(advent)
advent |> 
  select(entry_published, entry_title, entry_link, entry_author) |> 
  arrange(entry_published) |> 
  head(5) |> 
  gt::gt()

タイトルのところはいい感じの位置で改行したいし、URLも無駄に幅を取っていて、このまま表記するのはちょっと見た目的によろしくない。

こういう表に対して、

  1. 単純に改行したい
     → 改行したい位置に『\n』や『<br>』を挿入すればいいのでは?
     → そのままgt::gt()に渡しても改行してくれない

  2. ハイパーリンクを付けたい
     → str_c()とかで「<a ref=link>name<\a>」みたいに変形すればいいのでは?
     → そのまm(ry

という訳で、この辺りを何とかしたいと思って探していたら意外と資料が少なかったので、自分用のメモも兼ねて紹介したい。


文字列の改行 - gt::md()

gt::md()は受け取った文字列をマークダウン記法としてgt::gt()で扱えるようにするための関数。
実際の処理としては、改行したい文字列に予め「<br>」を仕込んでおいて、gt::md()を噛ませてからgt::gt()に渡せばいい。

何もしないとこんな感じ。

advent |> 
  select(entry_published, entry_title, entry_author) |> 
  arrange(entry_published) |> 
  head(5) |> 
  gt::gt()

改行を入れることで見やすくすることができる。
ゴリ押しで改行を捻じ込んでいるのはご愛敬。

advent |> 
  select(entry_published, entry_title, entry_author) |> 
  arrange(entry_published) |> 
  dplyr::mutate(
    entry_title = str_replace(entry_title, "他の人の|時間を|を使って", "\\0<br>") |> purrr::map(gt::md),
    .keep="unused"
  ) |> 
  head(5) |> 
  gt::gt()


表にリンクを置く - gt::html()

gt::html()gt::md()のhtml版みたいなもの。
これを利用してハイパーリンクを付ければいい。

htmlについては直接書いてもいいが、データから変換するならhtmltoolsパッケージを使うと便利。
また、リンクを入れたい文章に改行も入れる場合はマークダウン記法で書いてgt::md()で変換すればいい。

advent |> 
  select(entry_published, entry_title, entry_link, entry_author) |> 
  arrange(entry_published) |> 
  mutate(
    entry_title = str_replace(entry_title, "他の人の|時間を|を使って", "\\0<br>") |> purrr::map(gt::md),
    .keep="unused"
  ) |> 
  mutate(
    #entry_title = map2(entry_link, entry_title, \(x,y) htmltools::a(href=x, y) |> as.character() |> gt::html()),
    #entry_link = stringr::str_c("[", entry_title, "](", entry_link, ")") |> purrr::map(gt::md),
    entry_link = glue::glue("[{entry_title}]({entry_link})") |> purrr::map(gt::md),
    .keep="unused"
  ) |>
  head(5) |> 
  gt::gt()


まとめ

gtパッケージはいいぞ。


Enjoy!