niszetの日記

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

(R) drakeパッケージを頑張って使う…(必要は今はないよ…)

早くCRAN版が更新されてほしい…

さて、drakeパッケージですが、現状ではまだまだ問題があって色々と使いにくいところがあります。 前回あんなに推したのにね!

niszet.hatenablog.com

filterとの相性が悪い。

たとえば、下記のコードをRmd中のchunkとして使用すると正しくknitされてhtmlなりwordなりが生成されます。

plan <- drake_plan(
  ss = summary(cars),
  cc = cat("hoge"),
  strings_in_dots = "literals",
  iris_ = readr::read_csv("iris.csv"),
  # 以下のコメントを外すと動作しない 
  # iris_0 = iris_ %>% dplyr::filter(.$Sepal.Length > 3),
  iris__ = iris_ %>% mutate(hoge = Sepal.Length) %>% mutate(hoge2 = ifelse( stringr::str_detect("^s", string = .$Species), "h", "j")) %>%
    ggplot()+geom_point(aes(x=Sepal.Length, y=Sepal.Width))
)
config <- drake_config(plan)
make(plan)
vis_drake_graph(config)
readd(ss)
readd(cc)
readd(iris_)

これを実行するとこんな感じのdependency graphが作れます。

f:id:niszet:20180509002357p:plain

filterに関してissueを漁ると、例えば以下のようなものが見つかります。

github.com

どうやらCodeDependsパッケージが悪いらしい。ということで以下のコマンドで入れてみようとする。

devtools::install_github("duncantl/CodeDepends")

が、これをやろうとすると以下のようなエラーが出ます。

ERROR: dependency 'graph' is not available for package 'CodeDepends'

なんなのさ…とCRANの方を見に行くと、

https://cran.r-project.org/web/packages/graph/index.html

Package ‘graph’ was removed from the CRAN repository.

Formerly available versions can be obtained from the archive.

This package is now available from Bioconductor only, see <http://www.bioconductor.org/packages/release/bioc/html/graph.html>.

と、Bioconductorに行けと言われるので行ってみます。

www.bioconductor.org

中段にある2行を実行します。

source("https://bioconductor.org/biocLite.R")
biocLite("graph")

そうするとなんか入りますね

Bioconductor version 3.6 (BiocInstaller 1.28.0), ?biocLite for help
A new version of Bioconductor is available after installing the most recent version of R; see
  http://bioconductor.org/install

現状だとgraphの依存パッケージがCRAN上でバイナリがないため、コンパイルする?って聞かれるので対象は全部コンパイルしてでも最新のものを入れます。

graphとその依存パッケージが無事にはいったら改めて

devtools::install_github("duncantl/CodeDepends")

を実行します。

*** arch - i386
 警告:  replacing previous import 'graph::addNode' by 'XML::addNode' when loading 'CodeDepends'
 警告:  replacing previous import 'graph::plot' by 'graphics::plot' when loading 'CodeDepends'
*** arch - x64
 警告:  replacing previous import 'graph::addNode' by 'XML::addNode' when loading 'CodeDepends'
 警告:  replacing previous import 'graph::plot' by 'graphics::plot' when loading 'CodeDepends'

こういう警告が出ますが、まぁgraphわざわざ入れましたからね…。無視します。

このあと、RをRestartして、最初のfilterのコメントアウトを外すと動くはずです。

が、なんか最初typoしていたみたいなので、上記のコードは本当は動いたのかも。ただ、別の環境でfilterを使用して動かないことはあったので、それを回避するには上記の一連の作業が必要です。面倒くさいですね。

それでもダメな時がある。

ごくまれにですが、filter(.$列名 == 条件)のように.$を列名の前につけないとダメな時があります。というより、↑のコードも外すとなりますね。readd()していないのでエラーになりませんが。
これはvis_drake_graph()で対象の列が謎のMissing扱いのObjectになっていることから分かります。一応このときもdrake_config()make()は通るはずで、readd()しなければ問題は起こらないはずです。filter()を使用したplanを作ったらまずdependency graphを確認しておくと良いと思います。

htmltools$tags などはダメっぽい。

Rmd中にdrakeのコードを埋め込んだり、knitrのoptionを受け取ったりすることは問題なくできるようですが、htmltoolsでhtmlのタグを返してRmd中に埋め込んでみた箇所は動きませんでした。これはまだ深追いしていないので良く分からないけど。

結論

drakeパッケージを本格的に使うにはまだ早すぎる。

が、前処理部分の処理の要不要を判断してskipしてくれているような気がするので、knit時の実行時間がかなり短縮されている気がします。うまく使いこなせれば便利なんですがねぇ…。安定したCRAN版が出るまでは本番環境で使用するのは避けた方が良いかな、と思います。今触っておくのも楽しいとは思いますけどね!

他にも注意すべき点が何点かあって、drakeの関数の引数として与えるので代入は<-ではなくて=であるんだけど、当然その外は普通のRのコードなので<-で与えるべきとか、""を使うときはオプションを設定するだとか、dependencyはチェックしてくれるけどソースの違いはgitで管理しないといけないとか、同名の変数は定義できないので、順に足しているようなコードの場合はそれぞれを別名に書きなおさなくてはいけないとか。

暗黙の依存性は多分上記で解決しているはずなんだけど、発生した場合は良く分かりませんね。Rmd中で書いたコードのdiagnoseがグローバル環境で参照できるのも謎。.drake/を読みに行ってるからなんだろうか。

長大なコードの場合、dependency graphも複雑になってよくわからなくなります。たぶんこれはRmdを階層化して、その階層構造そのものをdrakeで管理、個別のRmdもdrakeで管理、依存関係は別途レポートしつつRmdの出力はhtmlなど所望の形に…という感じかなーと思うのですが、それをやるなら機能群としての何かしらのパッケージの形態が良いのかな、と。

RStudio IDEは階層構造をもったRスクリプト、Rmdなどの管理にはあまり強くないので、ドキュメントの規模が大きくなってきた際にそれを管理する方法は現状ではベストと言えるものはないのかなと思います。が、drakeはそれを解決するための答えの候補なのではないかなと思って注目している次第です。

まぁ実際は前処理コードが長いので、差異がなければ処理をスキップしてくれるようになってくれるだけでdrakeの価値があると僕は思っている(つまり、依存関係の管理ではなくてknitの処理時間の短縮に興味がある。中間結果を保存しているので1度実行すればそのチャンクをeval=FALSEすればよいのだが、それを毎回行うのは大変なのだ)

取り留めない感じになってきましたのでこのあたりで。

Enjoy!!