targetsプロジェクト組織のベストプラクティス
最終更新日:2026-11-10 | ページの編集
所要時間: 20分
概要
質問
-
targetsプロジェクトを整理するためのベストプラクティスは何ですか? -
targetsのワークフローの組織はスクリプトベースの分析とどのように異なりますか?
目的
- 最大限の再現性のために
targetsプロジェクトをどのように整理するかを説明する -
targetsの文脈で関数をどのように使用するかを理解する
Episode summary: プロジェクト組織のベストプラクティスを実演する
ワークフロープランをより簡単に書く方法
プラン内でターゲットを指定するデフォルトの方法は、tar_target()
関数を使うことです。
しかし、この書き方は少し冗長に感じるかもしれません。
その代わりに、targetsの開発者であるWill
Landauによって作成された tarchetypes
パッケージを使う方法があります。
tarchetypes のインストール
まだインストールしていない場合は、install.packages("tarchetypes")
で tarchetypes をインストールしてください。
tarchetypes の目的は、targets
パイプラインの記述を容易にするさまざまなショートカットを提供することです。
今回はそのうちの一つ、tar_plan() を紹介します。これは
_targets.R スクリプトの最後にある list()
の代わりに使用されます。
tar_plan() を使用することで、tar_target()
を使用してターゲットを指定する代わりに、target_name = target_command
のような構文を使用できます。
ペンギンのワークフローを tar_plan()
構文を使用するように編集しましょう:
R
library(targets)
library(tarchetypes)
library(tidyverse)
clean_penguin_data <- function(penguins_data_raw) {
penguins_data_raw |>
select(
species = Species,
bill_length_mm = `Culmen Length (mm)`,
bill_depth_mm = `Culmen Depth (mm)`
) |>
drop_na() |>
# Split "species" apart on spaces, and only keep the first word
separate(species, into = "species", extra = "drop")
}
tar_plan(
penguins_csv_file = "data/penguins_raw.csv",
penguins_data_raw = read_csv(penguins_csv_file, show_col_types = FALSE),
penguins_data = clean_penguin_data(penguins_data_raw)
)
読みやすくなったと思いませんか?
tar_plan()
を使用するからといって、すべてのターゲットをこの方法で書かなければならないわけではありません。tar_plan()
内で tar_target()
フォーマットを使用することもできます。
これは、= が短く読みやすい一方で、targets
が提供できるすべてのカスタマイズを提供しないためです。
今のところあまり重要ではありませんが、より高度な targets
ワークフローを作成し始めると重要になります。
ファイルとフォルダの整理
これまで、すべてを単一の _targets.R
ファイルで行ってきました。
これは小規模なワークフローには問題ありませんが、ワークフローが大きくなるとあまりうまく機能しません。
コードを整理するためのより良い方法があります。
プロジェクトフォルダ内に、_targets.R 以外の R
コードを保存するための R
という新しいディレクトリを作成しましょう(_targets.R
はサブディレクトリではなく、プロジェクト全体のディレクトリに配置する必要があることを覚えておいてください)。
R/ の中に functions.R という新しい R
ファイルを作成します。 ここにカスタム関数を配置します。 今すぐ
clean_penguin_data() をそこに入れて保存しましょう。
同様に、library() 呼び出しを R/ 内の
packages.R
という独自のスクリプトに配置しましょう(ただし、これは唯一の方法ではありません。“パッケージの管理” エピソード
を参照してください)。
また、_targets.R スクリプトをこれらのスクリプトを
source で呼び出すように修正する必要があります:
R
source("R/packages.R")
source("R/functions.R")
tar_plan(
penguins_csv_file = "data/penguins_raw.csv",
penguins_data_raw = read_csv(penguins_csv_file, show_col_types = FALSE),
penguins_data = clean_penguin_data(penguins_data_raw)
)
これで _targets.R
はずっとスリムになりました:ワークフローに集中し、各ステップで何が起こるかをすぐに教えてくれます。
最後に、データや出力など、コードではないファイルを保存するためのディレクトリを作成しましょう。
生データファイル用の data
ディレクトリはすでに作成しました。プロジェクトフォルダ内に、もう1つ
results
という新しいディレクトリを作成してください(バージョン管理を使用している場合は、_targets
ディレクトリに加えて、data と results
も無視することをおそらく望むでしょう)。
プロジェクトフォルダは、次のようになっているはずです:
.
├── _targets/ <- the targets cache (created by targets; do not edit)
├── _targets.R <- the workflow
├── R/
│ ├── functions.R <- custom functions
│ └── packages.R <- package loading
├── data/ <- input data files
└── results/ <- output files
関数についての一言
このレッスンの前半でカスタム関数について触れましたが、これはさらに明確化が必要な重要なトピックです。
targets
のような単一のワークフローではなく、複数のスクリプトを使用して R
でデータを分析することに慣れている場合、多くの関数(function()
関数を使用)を書かないかもしれません。
これは targets との大きな違いです。
カスタム関数を使用せずに効率的な targets
パイプラインを書くのは非常に難しいでしょう。なぜなら、ビルドする各ターゲットが単一のコマンドの出力でなければならないからです。
このカリキュラムでは R での関数の書き方をカバーする時間がありませんが、このトピックを復習するためには Software Carpentry のレッスン をお勧めします。
もう一つの大きな違いは、各ターゲットが一意の名前を持たなければならない ということです。 以下のようなコードを書くことに慣れているかもしれません:
R
# ペンギンの体重をグラムで保存し、キログラムに変換する
body_mass <- 3750
body_mass <- body_mass / 1000
同等の targets
パイプラインを実行しようとするとエラーが発生します:
R
tar_plan(
body_mass = 3750,
body_mass = body_mass / 1000
)
エラー
Error:
! Error in tar_make():
duplicated target names: body_mass
See https://books.ropensci.org/targets/debugging.html
targets
パイプラインで作業する大部分は、適切なサイズのカスタム関数を書くことです。
それらは単一行のコードだけになるほど小さくてはいけません;そうするとパイプラインが理解しにくくなり、維持管理が難しくなります。
一方で、変更に過度に敏感になるほど大きくしてはいけません。
このバランスを取ることは科学というよりもアートであり、練習を通じてしか習得できません。私が見つけた良い経験則は、ターゲットごとに3つを超える入力を持たないことです。
- コードを
R/フォルダに配置する - 関数を
R/functions.Rに配置する - パッケージを
R/packages.Rに指定する - データファイルを
data/に、出力ファイルをresults/に配置する - 関数を書くことは
targetsパイプラインの重要なスキルである