自分の現在のデータ解析の相棒は主に R です。簡単な解析であれば R スクリプトのファイルを一つ作って解析を行えばよいのですが、解析が長くなってくるとスクリプトが非常に長くなったり、関数を定義したりと行う作業が増えてきます。そのような状況下で、特に何のルールも設けずにファイルやフォルダを増やしていくと後で解析をやり直す際に、目的の操作を行った箇所を見つけ出すことができなかったり、最悪自分で行った解析を自分で再現できなくなったりします。そのようなことを避けるために自分が気をつけていることをリストしてみます。
データ解析・コード作成を行う際に気をつけるべきことがイギリス生態学会が公開している Guides to Reproducible Code でとてもよくまとめられています。以下でリストしている項目のいくつかについても触れられていますので、参考にしてみてください。
また、Guides to Better Science の Website ではその他のガイドも公開されています。こちらも興味ある方は御覧ください。
以下で解説しているルールは、例えばここで実践しています (Ushio 2019 Methods in Ecology and Evolution で使用したコードです)。
1. ファイル・フォルダ関係
ファイル・フォルダ名
- できるだけシンプルな、しかし中身を想像できる英語でつけます。日本語は使いません (日本語は bug の原因になったりする)。“data”, “function”, “fig” など。
- 解析スクリプトのような順番があるものにはファイル名の先頭に番号をふっています (“01_XXXXX.R”, “02_XXXXX.R” など)。ファイルの並び替えが容易になりますし、解析の順番が明示的になります。ちなみに自分は番号を 01, 02, …, などと2桁にしています。ファイル数が 10 を超えることがあるからです。
- あまりやりたくはないのですが、サブの番号を使うこともあります。例えば、“01_1_XXXXX.R” などです。
- 基本的に “-” は使いません。つなぎの文字としては “_” (アンダーバー) が好きです。
“data” フォルダ
- 解析するデータを格納するフォルダは常に “data” という名前をつけています。また、“data” フォルダ内のファイルはマニュアルでは (= 作業記録が残らない方法では) いじらないようにしています。
“function” フォルダ
- だいたいの解析において処理を効率化するための自作関数を使用することになるので、そのような関数は一括して “function” フォルダに格納しています。
“FigCode” フォルダ
- 自分は Figure の作成・体裁の調整をあとでまとめて行っており、そのためのコードを一括して “FigCode” フォルダに格納しています。この辺は好みによりそうです。
出力フォルダと計算結果の保存
- R スクリプトファイルと同じ名前 + “Out” を計算結果を格納するフォルダ名にしています。“01_XXXXXOut” などとなります。
- R スクリプト内に出力フォルダを生成するコードを書いています。
dir.create("01_XXXXXOut")
で生成できます。 - 計算結果の保存は次の2つの方法のどちらかを使っています。1つ目は workspace をまとめて保存する方法で、以下のコマンドを使っています:
save(list = ls(all.names = TRUE), file = "filename.RData")
。2つ目は R オブジェクトを単体で保存する方法で、以下のコマンドを使っています:saveRDS(object, "filename.obj")
。workspace を保存すると全オブジェクトが保存されますが、それではファイルサイズが重くなりすぎるときや、オブジェクトの数が増えすぎているときには、以後の解析で必要なオブジェクトだけを選んで保存して以後の解析で使用する、という風に使い分けています。
セッション情報保存用フォルダ
- 計算結果だけでなく R のバージョン・パッケージのバージョンなどの情報を格納するためのフォルダを作成しています。“00_SessionInfo” というフォルダを最初のスクリプトで作っています。
dir.create("00_SessionInfo")
としています。 - 各解析スクリプトの最後にセッション情報を取得して、保存するためのコードを書いています。
Sys.time()
関数を使用して解析を行った日付も同時に記録するようにしています。
writeLines(capture.output(sessionInfo()),
sprintf("00_SessionInfo/01_SessionInfo_%s.txt", substr(Sys.time(), 1, 10)))
以下のような感じでセッション情報が保存されます。何のパッケージのどのバージョンを使って解析したのか、あとからでもこれを確認すれば一目瞭然です。
例
上記のルールを実行していくと以下のような見てくれのフォルダ構造となります (下の例では “data” フォルダは “sampledata” と “seqdata” に分かれています)。自分としては解析の順番も見やすく、あとから解析のし直しもやりやすいので気に入っています。「解析は良くも悪くも必ずやり直しが必要になる」 ということは意識しています。
2. スクリプトの書き方
スクリプトの始まり
- 完全に個人ルールですが、最初にメモ的なものを書くようにしています。例えば次のような感じです。# を4つ入れているのも特に意味はありません。
####
#### R script for Ushio (2020)
#### "Use of a filter cartridge combined with intra-cartridge bead beating improves detection of microbial DNA from water samples"
#### No.1 Sequence analysis by DADA2
#### 2019.2.19 Ushio
#### R 3.5.2
####
パッケージのロード
- パッケージをロードする際に毎回バージョンを確認するようにしています:
library(xxxxx); packageVersion("xxxxx")
。
コメント
- 処理の前に何をするか説明するコメントを (面倒でも) 書いています。例えば以下のような感じです。
# Load library
library(xxxx); packageVersion("xxxx")
# Load previous workspace
load("01_xxxxxOut/01_xxxxxOut.RData")
他の言語の利用
- R 以外の言語を利用することがありますが、それら言語に応じて対応しています。
- C++ (あまり得意でないです)、Python は Rstudio 内でそのまま利用できます。C++ は Rcpp パッケージを、Python は reticulate パッケージで対応しています。
- DNA 配列解析ではよくシェルを利用する場合がありますが、短いコードであれば R の
system()
関数などを使って R 内で対応しています。
3. 作図
作図は最近はもっぱら ggplot2 パッケージを利用しています。保存した解析の結果 (workspace ファイルもしくはオブジェクトファイル) をロードして、ggplot()
関数で作図する感じです。一点気を使っているのは、特別な理由がない限り画像編集ソフトでいじらない という点です。たまに細かい部分を編集したいときにコードでどう書いたらいいかわからないことがありますが、時間をかけてでも調べて、図の全てをコードで再現できるように努力しています。面倒でもそうした方が研究の再現性は上がりますし、改訂などのときに自分自身が楽になると思っているからです。さすがにイラストは画像編集ソフトを使いますが。
(ただし、これに成功したのは Ushio 2019 の DNA 抽出論文からです)
利用している ggplot2 の関連パッケージ
作図では ggplot2 に加えて、以下のお助けパッケージのお世話になっています。特に cowplot はヘビーに使っています (詳しい使い方は今回は省略します)。
cowplot (チュートリアル)
主に複数のパネルを配置するときに使っています。plot_grid()
関数にはいつもお世話になっています。
ggsci (ここで公開されている Rmd とかが便利です)
あまり手間をかけずにそれなりにかっこいい配色をしたいときに使っています。一方、本気でやりたいときには使ってなかったりします。
ggrepel (チュートリアル)
妙にいい感じにプロット内にラベルを付けてくれます。便利です。
Rmarkdown による図の結合
作図が全部できたら最後に Rmarkdown の機能を使って図をまとめて、Figure legend もくっつけています。Rstudio の “New File” には “R Markdown” という選択肢があるので、それをクリックして R Markdown の新しいファイルを作ります。
ヘッダー部分 (YAML と呼ばれます) でいろいろと Rmarkdown に関する設定をするのですが、一番シンプルな場合には以下のように記載しています。
title: "XXXXXX"
author: "Masayuki Ushio"
date: "XX/XX/XXXX"
output:
pdf_document:
fig_caption: yes
その後、以下のコードを使って図をどんどんまとめていきます。
![caption](../0_Figs/Fig1_xxxxx.pdf)
4. まとめ
- いろいろと書いてみましたが、結局の所 「将来、他人が見たときに何をやったか分かるように構成できていて、全く同じ結果を再生産 (reproduce) できれば最高」 です。
- いきなりそこまで行くのは様々なケアが必要なので実はかなり大変ですが、「少なくとも自分が将来見直したときに何をやったかきちんと思い出せるように構成する」 という部分がスタート地点かなと思いました。
- 最近は、解析がどんどん複雑になってきていて、docker などのツールの利用も進んできています。docker はビギナーなので、まだまだ修行しながら頑張りたいと思います。
Written with StackEdit.