niszetの日記

アナログCMOS系雑用エンジニアが頑張る備忘録系日記

(R) もう少し具体的な形での、Rmdを書くときのファイル等の階層構造についてのメモ

試行錯誤している

この前の記事、

niszet.hatenablog.com

Twitter上でuriboさんが反応してくれたので、現在のRmd内の構成とプロジェクト内でのファイル構造について書いてみる。

前回はまずはRファイルにまとめる、そのあとRファイル中の関数群をchunkと定義してRmdからそのchunkを呼び出す、という形で対応しているという話でした。

シンプルな、関数が2-3個くらいならまぁコレで良さそうなのですが、段々とあれも欲しいこれも欲しい…でファイルが成長していくことがままありまして、その途中経過について、ここでは書いています。

プロジェクト内の階層構造

ネットで見かけた、

R/
data/
output/
doc/

の構成が良さげなのでこれを採用しています。基本的にはパッケージ作るときの階層構造+data/、output/って感じですかね。
このあたりも試行錯誤していて、ガチの生データ(ログファイルとか)と、それをcsvにしたものは別にするとして、csvはoutputなのか…?という感じに(今はそうなっているが…)

中間データとして、生データとも最終データとも分けておいた方が良い感じはしますね。分けよう…。

R/の下も似ている関数は全部まとめておきたいところですが最初のうちはどうなるのかわからん…。
ファイルが成長していくと、他のRファイルの関数を呼び始めるので、そこまで複雑になってきたらパッケージ化を考えた方が良いのかもしれないですね。

Rmd中の構造

  • setupチャンク これは普通のRmd中にも入れますね。

    • knitrのグローバルな設定
    • library類の読み込み
    • read_chunk()でRファイル内のchunkの読み込み。使用している関数の定義をしているもの(R/def/に入れている)とplotしているもの(R/plotに入れている)など、必要なRファイルは全部取り込んでおく必要がある。
  • definition系のchunkの実行

    • 自作関数の定義を有効にするためのchunk。この中では定義だけ有効にするように構成する(関数を実際に実行することはしない)
    • libraryなどもこの内部では実行せず。
  • chunk: data_path_definition

    • 内部で使用するファイルパスの定義のchunk
    • here("data" "data1.txt")で プロジェクトのtop dir/data/data1.txtになる。hereパッケージ便利。
    • Rmdをデータごとに作る場合、このファイルパスだけ対応するファイル名に変更すればよいように作っておくと、Rmdファイル量産が簡単にできる。プロットを並べて比較すような場合、データだけ入れ替えて図表は同じ構成ということがあるので、このファイルパスだけ更新すればよい、という形にしておくと結構楽にできる(本文が入るとダメだけど…それも外部からimport出来れば…)
  • データ前処理系のchunk

    • 生データに差異がない、あるいは整形したデータに変更を加えたくない、処理時間をかけたくない場合(ただし、この実行の結果如何で最終的な結果が変わらない場合に限る)はここをskip
  • data importのchunk

    • read_csv()とかでファイブのデータを読み込むchunk。ファイルパスは↑で定義。

以降は本文とplot系のchunk。もし、plot前になんらかの処理が必要であれば、それはplotのchunk内で行っている。 もし、変数等が共通で、オプションを変える必要がないのであれば、コード一式をRファイルに書き出すのもアリ。というよりはそうした方が良い。データパス依存のコードをRファイルに書き出してしまうと、Rmdを作るごとにRファイルが増えてしまうのでそれは避けるべき。変数名は同じにして、変数の中身は違うけど同じ処理をしている…という書き方がベターっぽい。

Rのコード単体でも動くようにしたかったのですが、依存関係の処理が結構面倒くさくて、「いや、そもそも複数のRのコードを管理するのはパッケージでは…?」と、思い直してそちらのスパゲッティ化は回避しました。ただ、単体のRファイルでも動作するというのは大事だと思っているのでこれはいずれ解決させたいと思っています(暫定解は他のファイル全部読む、パッケージ化する)

内部で使用するRのコードが増えてきたらパッケージ化を考えるのは良いと思いますが、初心者向きではないのと、外部パッケージの関数の使用をしている場合は割と面倒なので、このあたりのお作法を守って作るのはまだ「書き捨て」のつもりのRのコードを書いている段階ではちょっと書くコストに見合わないかなぁって思います。どこかに損益分岐点があるのですが、これがどこかわかっていない。
また、これは人によっても変わると思うので、一般論とするのは難しいかもしれない。

後からパッケージ化するためのバッドノウハウもあると思う。が、ある程度詳細を詰めることが出来たらそこから引いて、トップダウンで設計しなおした方が良い構造になるのではと思っています(が、現実にはそこに時間をかけること、難しく…)

前回よりもまとまっていませんが…こうやって情報?を出すことで、色々議論が出来ればいいなぁ…と思っています。

Reproducible Research with R and RStudio Second Editionに載ってるのかなー。やっぱり読むべきなんだろうか…

とりとめない…っ!!

Enjoy!!