/* terashim.com */

システム開発・データエンジニアリング・データ分析についての個人的なノート

Target Markdown 検証メモ

R パッケージ targets の次期バージョン 0.5.0 でリリース予定の Target Markdown の動作について検証しました。

targets とは

targets は R のパイプラインツールです。 開発停止となった drake の後継プロジェクトという位置づけになっています。

targets の使い方を理解するには、公式ユーザーマニュアルにあるチュートリアル

をなぞるのが最適です。

また、他の資料としては drake の活用方法を説明した記事

や、日本語の解説

などがあります。

Target Markdown とは

targets の次期バージョン 0.5.0 で Target Markdown がリリースされる予定になっています(2021/6/9 現在)。1 これは knitrtargets の専用エンジンを導入し、R Markdown 文書中でパイプラインを定義できるようになるというものです。

Target Markdown の基本的な使い方はユーザーマニュアルの "Chapter 3 Target Markdown" で説明されています。

調べたこと

ユーザーマニュアルに示されている例では、まず targets チャンクでパイプライン全体の定義を行ってから実行し、最後に結果を表示しています。 そのため、ターゲットを定義するコードとその実行結果が離れた位置に来てしまいます。 コードと結果の対応をわかりやすく示すためには、ターゲットの定義コードとその実行結果は近くに表示したいところです。 そこで、ターゲット定義コードの近くに実行結果を表示するにはどうすれば良いか検証しました。

わかったこと

検証の結果、次のことがわかりました。

  • すべての targets チャンクを実行する前に途中で tar_make() を実行すると、その時点までに完成したパイプラインが実行される。
  • targets チャンクを追加してからまた tar_make() を実行しても正しくキャッシュが効く。
  • ターゲット定義チャンクの近くにその実行結果を表示したい場合は、ターゲット定義チャンクの直後で tar_make()tar_read() を実行すれば良い。

検証用 R Markdown ソース

以下は検証に使用した R Markdown のソースコードです。 なお検証には GitHub 上にある ropensci/targets バージョン 0.5.0.9000 を使用しました。

---
title: "Target Markdown の検証"
author: "@terashim_"
date: "2021-06-08"
output: html_document
---
```{r setup, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>",
tar_interactive = FALSE)
```
# 目的
[`targets`](https://docs.ropensci.org/targets/) バージョン 0.5.0 でリリースされる
[Target Markdown](https://books.ropensci.org/targets/markdown.html)
の機能を利用すると、R Markdown 文書中で targets パイプラインを定義できる。
しかし、ドキュメントに示されている例ではターゲットを定義するコードとその実行結果が離れた位置に来てしまう。コードと結果の対応をわかりやすく示すためには近くに表示したい。
そこで、ターゲット定義コードの近くに実行結果を表示するにはどうすれば良いか調べる。
# わかったこと
* `targets` チャンクをすべて実行する前に `tar_make()` を実行すると、その時点までに完成したパイプラインが実行される。
* `targets` チャンクを追加してからまた `tar_make()` を実行してもちゃんとキャッシュが効く。
* ターゲット定義チャンクの近くにその実行結果を表示したい場合は、ターゲット定義チャンクの直後で `tar_make()``tar_read()` を実行する。
-----
# セットアップ
まず `targets` をロードする
```{r}
library(targets)
```
もし過去に生成されたパイプライン定義ファイル(`_targets_r` フォルダ)が残っていたら削除しておく
```{r}
tar_unscript()
```
もし過去のパイプライン実行結果(`_targets/` フォルダ)が残っていたら削除する
```{r}
tar_destroy()
```
# グローバルオブジェクトを定義する
targets のオプション設定やグローバル関数・グローバル変数の定義には
`targets` チャンクに `tar_globals = TRUE` のオプションをつける。
このチャンクを対話モードで実行すると普通にRコードとして実行され、グローバル環境の変数に値が代入される。
非対話モードで実行すると `_targets_r/globals/` フォルダにスクリプトファイルが作成される。
```{targets example-globals, tar_globals = TRUE}
options(tidyverse.quiet = TRUE)
tar_option_set(packages = c("biglm", "dplyr", "ggplot2", "readr", "tidyr"))
create_plot <- function(data) {
ggplot(data) +
geom_histogram(aes(x = Ozone), bins = 12) +
theme_gray(24)
}
```
# ターゲットを定義する
`targets` チャンクに `tar_globals` オプションをつけない場合、target オブジェクトの定義を表す。
このチャンクを対話モードで実行すると、単にグローバルオブジェクト `raw_data` にコマンド `airquality` の戻り値が代入される。
非対話モードで実行すると、`_targets_r/targets/` フォルダにターゲット定義用のスクリプトが生成される。
```{targets raw-data}
tar_target(raw_data, airquality)
```
# パイプラインの確認と実行
上記の `targets` チャンクが非対話モードで実行してあれば、`targets` パイプラインが定義されている。
この時点でパイプラインを可視化してみる。
```{r}
tar_visnetwork()
```
この時点でパイプラインを実行してみる
```{r}
tar_make()
```
もう一度パイプラインを可視化してみる
```{r}
tar_visnetwork()
```
# パイプラインにターゲットを追加する
`targets` チャンクでパイプラインにターゲットを追加する
```{targets downstream-targets}
list(
tar_target(data, raw_data %>% filter(!is.na(Ozone))),
tar_target(hist, create_plot(data))
)
```
またパイプラインを可視化する
```{r}
tar_visnetwork()
```
既に実行済みのターゲット `raw_data` は "Up to date" の状態に、
新しく追加されたターゲット `data`, `hist` は "Outdated" の状態になっている。
パイプラインを再実行する。
```{r}
tar_make()
```
"Up to date" だったターゲット `raw_data` の実行はスキップされ、新しいターゲット `data`, `hist` が実行される。
また可視化する
```{r}
tar_visnetwork()
```
すべて "Up to date" になっている。
ターゲット `hist` の実行結果を読み取って表示する
```{r}
tar_read(hist)
```
# `tar_simple = TRUE` オプション
また `targets` チャンクで新たなターゲットを追加する。
このとき `tar_simple = TRUE` オプションを利用する。
このチャンクは `tar_target(fit, biglm(Ozone ~ Wind + Temp, data))` でターゲットを定義するのと同じ意味になる。
```{targets fit, tar_simple = TRUE}
biglm(Ozone ~ Wind + Temp, data)
```
またパイプラインを可視化
```{r}
tar_visnetwork()
```
パイプラインを再実行
```{r}
tar_make()
```
また可視化
```{r}
tar_visnetwork()
```

レンダリングされたHTML

以下は上の R Markdown ソースを knitr でレンダリングした結果の HTML ページです。

Footnotes

  1. https://twitter.com/wmlandau/status/1398284741930008578