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

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

Rで解析:動的なHTMLレポートを作成するhtmlreportRパッケージ

解析結果をまとめたHTMLレポートは、表の並べ替えや絞り込みといった操作ができると、受け取った側が自分の関心に沿って中身を確かめられます。しかし、Rの出力からこうしたレポートを組み立てるには、JavaScriptやCSSの記述と、データの受け渡しの両方に手間がかかります。

「htmlreportR」パッケージは、テンプレートに書いた見出しとコマンドから動的なHTMLレポートを組み立てるためのパッケージです。データフレームを渡すだけで並べ替えや検索、ファイル出力に対応した表を作成でき、独自のJavaScriptやCSS、CDNの読み込みも指定できます。また、ワイルドカードを含むパスの展開や、見出し行・列の入れ替え、階層構造を持つHTMLリストへの変換など、レポートの中身を整えるためのコマンドも収録されています。本パッケージの利用で、静的なプロットだけでは伝えきれない結果を、動きのあるHTMLレポートとしてまとめられるのではないかと考えます。

パッケージバージョンは2.0.1。Windows 11 x64 (build 26200)のR version 4.6.1で確認しています。

パッケージのインストール

下記コマンドを実行してください。

# パッケージのインストール
install.packages("htmlreportR")

# パッケージの読み込み
library("htmlreportR")

スポンサーリンク

コマンド例

詳細はコメント、パッケージのヘルプを確認してください。

HTMLはハイパーテキストマークアップ言語、JSはJavaScript、CSSはCascading Style Sheetsの略称で、いずれもWebページを構成するための標準的な技術です。

本パッケージのレポートは、HTMLとRのコードを並べて書いたテンプレートを用意し、そこにデータを流し込んで組み立てます。はじめにレポート本体を作成するコマンドを確認し、その後にレポートの中身を整えるコマンドを確認します。

動的HTMLレポートの作成:htmlReportコマンド

レポートの土台となる参照クラスです。newメソッドでレポートオブジェクトを作成し、buildメソッドでテンプレートを読み込んで本体を組み立て、write_reportメソッドでHTMLファイルとして書き出します。containerオプションに渡したデータは、テンプレートの中でplotterという名前のレポートオブジェクトを通して参照します。

テンプレートに書くRのコードは、knitrのHTML用の記法である「<!–begin.rcode」から「end.rcode–>」までの範囲に記述します。

オプション意味初期値
containerレポートから参照するデータフレームなどをまとめた名前付きリストlist()
title_docレポートのタイトル“”
type_index見出し索引の形式、”contents_list”または”menu”“contents_list”
tmp_folder作業用の一時フォルダのパス、書き出し後に削除されるtempdir(check = TRUE)
srcパッケージの付属ファイルを格納したフォルダのパスfind.package(“htmlreportR”)
compress_obj埋め込むオブジェクトを圧縮するかの論理値TRUE
files_css追加で読み込む独自CSSファイルのパス、カンマ区切りで複数指定可NULL
files_js追加で読み込む独自JavaScriptファイルのパス、カンマ区切りで複数指定可NULL
cdn_jsCDNから読み込むJavaScriptのURL、カンマ区切りで複数指定可NULL
cdn_cssCDNから読み込むCSSのURL、カンマ区切りで複数指定可NULL

テンプレートの中では、レポートオブジェクトの各メソッドを呼び出して中身を作成します。主なメソッドは下記のとおりです。

メソッド意味
buildテンプレートを読み込みレポートの本体を組み立てる
write_report組み立てたレポートをHTMLファイルとして書き出す
tableデータフレームをHTMLの表に変換する
heatmapデータフレームをヒートマップとして描画する
barplotデータフレームを棒グラフとして描画する
lineデータフレームを折れ線グラフとして描画する
boxplotデータフレームを箱ひげ図として描画する
densityデータフレームを密度プロットとして描画する
scatter2Dデータフレームを散布図として描画する
static_plot_main任意の作図関数の結果を画像としてレポートに埋め込む
static_ggplot_mainggplot2による作図結果を画像としてレポートに埋め込む
embed_img画像ファイルをレポートに埋め込む
mermaid_chartMermaid記法で書いた図をレポートに埋め込む
prettify_div要素を囲む領域の体裁を整える
create_title見出しを作成し索引に登録する
# 宇治茶の生産量データを、1行目に見出しを含む形で作成
cha <- data.frame(
  V1 = c("地区", "宇治", "宇治田原", "和束"),
  V2 = c("生産量_kg", "1200", "950", "800"),
  V3 = c("面積_ha", "15", "12", "10"),
  stringsAsFactors = FALSE
)

# レポートから参照するオブジェクトをコンテナにまとめる
container <- list(ujicha = cha)
# テンプレートを作成、tableメソッドで動的な表を作成する
template <- c(
  "<h1>宇治茶の産地レポート</h1>",
  "<!--begin.rcode ujicha_table",
  "cat(plotter$table(list(id = \"ujicha\", header = TRUE, text = \"dynamic\",",
  "                       table_rownames = FALSE, styled = \"dt\")))",
  "end.rcode-->"
)
# テンプレートをファイルとして保存

writeLines(template, "ujicha_template.txt")
# レポートオブジェクトを作成
plotter <- htmlReport$new(container = container,
                          title_doc = "宇治茶の産地レポート",
                          tmp_folder = "tmp_ujicha")

# テンプレートを読み込みレポートを組み立てる
plotter$build("ujicha_template.txt")
# HTMLファイルとして書き出す
plotter$write_report("ujicha_report.html")
# 出力されたファイルを確認
file.exists("ujicha_report.html")
[1] TRUE

tableメソッドのstyledオプションに”dt”を指定すると、並べ替えや検索、コピーやCSV・Excel形式での書き出しができる動的な表になります。headerオプションにTRUEを指定した場合は、データの1行目が見出しとして扱われます。

スクリプトモードでのレポート作成:main_htmlreportRコマンド

ファイルの読み込みからHTMLの書き出しまでを一括で行います。データファイルとテンプレートの場所を設定リストにまとめて渡すだけで、レポートオブジェクトの作成から書き出しまでが内部で実行されます。

オプション意味初期値
optionsレポートの作成に必要な要素をまとめたリストなし

optionsに指定できる主な要素は下記のとおりです。初期値は、パッケージに付属するスクリプトhtml_report.Rで設定される値です。

要素意味初期値
data_files読み込むタブ区切りファイルのパス、カンマ区切りで複数指定可NULL
template読み込むテンプレートファイルのパスNULL
output_file書き出すHTMLファイルのパス、未指定時はテンプレートと同じ場所のreport.htmlNULL
titleレポートのタイトル“htmlreportR”
source_folderパッケージの付属ファイルを格納したフォルダのパスなし
uncompressed_datacompress_objに渡される論理値、TRUEで埋め込むオブジェクトを圧縮TRUE
css_files追加で読み込む独自CSSファイルのパス、カンマ区切りで複数指定可NULL
js_files追加で読み込む独自JavaScriptファイルのパス、カンマ区切りで複数指定可NULL
css_cdnCDNから読み込むCSSのURL、カンマ区切りで複数指定可NULL
js_cdnCDNから読み込むJavaScriptのURL、カンマ区切りで複数指定可NULL
menu見出し索引の形式、”contents_list”または”menu”“contents_list”
# 作業用のフォルダを作成
dir.create("kyoto_script", showWarnings = FALSE)
# 京野菜の出荷量データを作成
yasai <- data.frame(
  品目 = c("九条ねぎ", "賀茂なす", "万願寺とうがらし"),
  出荷量_kg = c(480, 320, 210)
)

# タブ区切りのテキストファイルとして保存
write.table(yasai, file.path("kyoto_script", "yasai.txt"),
            sep = "\t", quote = FALSE, row.names = FALSE)

# テンプレートを作成、idには読み込むファイル名を指定
template <- c(
  "<h1>京野菜の出荷量</h1>",
  "<!--begin.rcode yasai_table",
  "cat(plotter$table(list(id = \"yasai.txt\", header = TRUE, text = \"dynamic\",",
  "                       table_rownames = FALSE, styled = \"dt\")))",
  "end.rcode-->"
)

# テンプレートをファイルとして保存
writeLines(template, file.path("kyoto_script", "template.txt"))
# レポートの作成に必要な設定をリストにまとめる
opt <- list(
  data_files = file.path("kyoto_script", "yasai.txt"),
  template = file.path("kyoto_script", "template.txt"),
  output_file = file.path("kyoto_script", "kyoyasai_report.html"),
  title = "京野菜の出荷量レポート",
  source_folder = find.package("htmlreportR"),
  uncompressed_data = TRUE,
  menu = "contents_list"
)

# 設定を渡してレポートを一括で作成
main_htmlreportR(opt)
Reading file kyoto_script/yasai.txt

# 出力されたファイルを確認
file.exists(file.path("kyoto_script", "kyoyasai_report.html"))
[1] TRUE

title、source_folder、uncompressed_data、menuの各要素は、値がそのままレポートオブジェクトに渡されます。省略した場合はエラーになるため、いずれも指定してください。

以下のコマンドは、パスの解析や見出し行・列の入れ替え、特定の記号の置換など、レポートに載せるデータやテキストの形を整えるための独立した処理をまとめたコマンド群です。

パス文字列の解析:parse_pathsコマンド

ワイルドカードを含むパスの文字列を展開し、実際に存在するファイルのパスに変換します。カンマ区切りで複数のパスをまとめて渡すこともできます。

オプション意味初期値
string展開するパスを含む文字列なし
# 京都の直売所のCSVファイルを想定したフォルダを作成
dir.create("kyoto_report", showWarnings = FALSE)

# ファイルを作成
file.create(file.path("kyoto_report", c("uji_cha.csv", "kujo_negi.csv", "kamo_nasu.csv")))
[1] TRUE TRUE TRUE

# ワイルドカードを含むパスを解析する
dir <- "kyoto_report/*.csv"
parse_paths(dir)
[1] "kyoto_report/kamo_nasu.csv,kyoto_report/kujo_negi.csv,kyoto_report/uji_cha.csv"

列名の行名への変換:col_to_rownamesコマンド

指定した列の内容をデータフレームの行名に設定し、その列自体はデータフレームから取り除きます。

オプション意味初期値
data_frame操作対象のデータフレームなし
col新しい行名に設定しデータフレームから削除する列番号1
# 宇治・宇治田原・和束の茶生産量データを作成
sanchi <- data.frame(
  地区 = c("宇治", "宇治田原", "和束"),
  生産量_kg = c(1200, 950, 800),
  面積_ha = c(15, 12, 10)
)

# 地区列を行名に変換する
col_to_rownames(sanchi, col = 1)
         生産量_kg 面積_ha
宇治          1200      15
宇治田原       950      12
和束           800      10

宇治茶や京野菜の生産統計をHTMLレポートに載せる際、地区名を行名にしておくと、後段のコマンドで表を扱いやすくなります。

HTML形式のリスト生成:make_html_listコマンド

要素のベクトルをHTMLの順序なしリスト(ul)または順序付きリスト(ol)に変換します。list_levelsオプションで要素ごとの入れ子の深さを指定すると、階層構造を持つリストも作成できます。

オプション意味初期値
list_contentリストを構築する要素のベクトルまたはリストなし
list_levels要素ごとの入れ子の深さを定めるベクトルまたはリストNULL
list_types要素ごとに割り当てるリストの種類(”ul”または”ol”)のベクトルまたはリスト、未指定ならdefault_typeに従うNULL
default_typelist_types未指定時に使うリストの種類、”ul”(順序なし)または”ol”(順序付き)“ul”
# 観光エリアとスポットを、入れ子の深さとともに定義
content <- c("嵐山エリア", "渡月橋", "竹林の小径", "伏見エリア", "伏見稲荷大社")
levels <- c(0, 1, 1, 0, 1)

# 階層構造を持つHTMLリストを作成
make_html_list(list_content = content, list_levels = levels)
[1] "<li>嵐山エリア</li>\n<ul>\n<li>渡月橋</li>\n<li>竹林の小径</li>\n</ul>\n<li>伏見エリア</li>\n<ul>\n<li>伏見稲荷大社</li>\n</ul>\n"

特定の記号の置換:replace_paired_markコマンド

文字列の中からパターンに一致する箇所を探し、ペアで挟まれた部分を別の記号やタグに置き換えます。Markdown風の強調記号をHTMLタグに変換する用途に向いています。

オプション意味初期値
string編集対象の文字列なし
pattern再帰的に置換するパターン(正規表現)なし
replace置換後の開始側・終了側の文字列を、この順で含むベクトルなし
# レポートの見出しに使うメモを定義
memo <- "本日の目玉は **宇治茶** です"

# アスタリスクで挟んだ部分を検出するパターンを定義
pattern <- "(\\*\\*+?)([^*]+)(\\*\\*+?)"

# ペアの記号をHTMLタグに置換
replace_paired_mark(memo, pattern, c("<strong>", "</strong>"))
[1] "本日の目玉は <strong>宇治茶</strong> です"

行のヘッダーへの変換:row_to_headerコマンド

指定した行の内容をデータフレームの列名として設定し、その行はデータフレームから取り除きます。見出しが本来のヘッダーではなくデータの1行目に紛れ込んだ状態で読み込んでしまった場合に使えます。

オプション意味初期値
data_frame操作対象のデータフレームなし
row新しい列名に設定しデータフレームから削除する行番号1
# 見出しがデータの1行目に紛れ込んだ京野菜の出荷量データ
yasai <- data.frame(
  V1 = c("品目", "九条ねぎ", "賀茂なす", "万願寺とうがらし"),
  V2 = c("出荷量_kg", "480", "320", "210"),
  stringsAsFactors = FALSE
)

# 1行目を列名に変換する
row_to_header(yasai, row = 1)
              品目 出荷量_kg
2         九条ねぎ       480
3         賀茂なす       320
4 万願寺とうがらし       210

tableメソッドにheaderオプションを指定した場合も、内部でこのコマンドが呼び出されます。


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

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