1. okiyuki99

    Posted

    okiyuki99
Changes in title
+Rのパッケージ管理のためのrenvを使ってみた
Changes in tags
+R
Changes in body
Source | HTML | Preview
@@ -0,0 +1,218 @@
+## renv とは?
+RStudioが開発を進めているRのPackage管理のためのパッケージである
+
+パッケージ管理といえば、Pythonでは新しいパッケージが次々出ており、流れをキャッチアップするだけで一苦労だが、RではこれまでRStudio社の`Packrat`くらい?しかなかったように思える(私が知らないだけかもしれないが)
+
+パッケージ管理が必要な理由としては、Rの場合は主に分析の再現性を担保するためだと思う。とくに、複数人でRプロジェクトをおこなうときに威力を発揮する。また自分の場合、CIでテストを行うときやShiny Appを開発するときにも威力を発揮している
+
+なぜ`renv`が開発されているかの背景を理解するために`renv`の[Project page](https://rstudio.github.io/renv/)に書いてあるGoalを見てみる
+
+> The goal is for renv to be a robust, stable replacement for the Packrat package, with fewer surprises and better default behaviors.
+
+この一文から、`Packrat`を代替しながら、より安定して使いやすいものを目指していることがわかる。`Packrat`を使ってるRユーザはどれくらいいるのだろうか。少なくとも自分の周りで`Packrat`使ってますという話はほとんど聞かない(自分はそこそこ使ってたほうだと思う)
+
+([Packratの使い道を考えてみた](https://qiita.com/uri/items/5d473a5df91954585e62)がとても詳しいので、Packratの解説は省略します)
+
+## `Packrat`との違い
+
+`renv`の`Packrat`との違いは[Project Page](https://rstudio.github.io/renv/articles/renv.html#comparison-with-packrat)に書かれている。大きいところとしては、`renv.lock`というjson形式でRプロジェクトで使用しているパッケージのメタ情報を保存してくれることや、global cacheという仕組みでRプロジェクト間でパッケージを共有できる仕組みがある。そのため、Rプロジェクトを変更するごとに、毎回CRANにパッケージをダウンロードする待ち時間が発生するのはほとんどなくなった点が大きい
+
+global cacheは簡単に言うと、ローカルのhomeディレクトリのような決められた配下にパッケージを保存して、Rプロジェクトで利用するときに、キャッシュがあるなら、そこへのリンク(正式にはシンボリックリンク)を貼ってくれる仕組みである
+
+## 個人的な感想
+
+`Packrat`をそこそこ使ってた私の感想としては、global cacheにより待ち時間が減り、デフォルトの挙動が覚えやすいので、今のところ使いやすい印象です。そのため、Rでパッケージ管理したことがない方へも導入のしきいは低くなっていると感じます
+
+
+## 参考情報
+* Github : https://github.com/rstudio/renv
+* Project page : https://rstudio.github.io/renv/
+ * "Using renv with Docker" のArticles読めばDocker Image作るときに楽になると思います
+* Snapshot and Restore : https://environments.rstudio.com/snapshot
+ * この記事が流れをみるのにわかりやすい
+
+## インストール
+
+2019-08-16時点では、CRANにはまだアップロードされていないので、Githubからインストールする
+
+```R
+> remotes::install_github("rstudio/renv")
+<snip>
+> packageVersion("renv")
+[1] ‘0.6.0.108’
+```
+
+## 基本的な使い方
+
+### 同じホストでの作業
+
+1. `renv::init()` をする
+2. Rコードを書く
+3. `renv::snapshot()` をたまにする
+4. 作業を終えたら、`renv::snapshot()`をして、編集したファイルとともに `renv/`と`renv.lock` ファイルらをgit commitする
+
+### 違うホストから使うとき
+
+1. git clone したのちに、`renv::restore()`
+2. あとは同じ
+
+それぞれ主に使うコマンドを簡単に解説する
+
+### ```renv::init()```
+
+`renv`によるパッケージ管理を始めるために使用する
+
+実行すると、`renv/`というprivate R libraryの置き場と、`.Rprofile`が作成される
+
+`.Rprofile`には、```source("renv/activate.R")``` が記載されており、Rプロジェクト開始とともに`renv`によるプロジェクト管理をスタートする処理が書かれている
+
+```R
+> renv::init()
+* Discovering package dependencies ... Done!
+* Copying packages into the cache ... [300/300] Done!
+* Resolving missing dependencies ...
+* Querying repositories for available source packages ... Done!
+Retrieving 'https://cloud.r-project.org/src/contrib/fclust_2.1.tar.gz' ...
+ OK [downloaded 86.2 Kb in 0.8 secs]
+<snip>
+```
+
+完了後、`.libPaths()`を実行してみると、private R libraryが使われている事がわかる(2つめはよくわかっていない)
+
+```
+> .libPaths()
+[1] "/home/ooki/renv-sandbox/renv/library/R-3.6/x86_64-pc-linux-gnu"
+[2] "/tmp/RtmpUk1Icd/renv-system-library"
+```
+
+このときprivate R library配下にパッケージのソースが置かれるのではなく、global cache配下(Linuxだと`~/.local/share/renv`)に置かれ、private R libraryにはそこへのリンクが置かれる
+
+```console
+$ ls -la ~/renv-sandbox/renv/library/R-3.6/x86_64-pc-linux-gnu/
+<snip>
+lrwxrwxrwx 1 ooki ooki 124 Aug 16 19:24 assertthat -> /home/ooki/.local/share/renv/cache/v4/R-3.6/x86_64-pc-linux-gnu/assertthat/0.2.1/87318c127c936afe4da4d066d1fd01c3/assertthat/
+lrwxrwxrwx 1 ooki ooki 122 Aug 16 19:24 backports -> /home/ooki/.local/share/renv/cache/v4/R-3.6/x86_64-pc-linux-gnu/backports/1.1.4/8ed7589b3c92d5dc620c45b5f0909d9f/backports/
+lrwxrwxrwx 1 ooki ooki 111 Aug 16 19:23 BH -> /home/ooki/.local/share/renv/cache/v4/R-3.6/x86_64-pc-linux-gnu/BH/1.69.0-1/a3839f6fcfa121ea0b5c4b3a0b42456e/BH/
+<snip>
+```
+
+### ```renv::snapshot()```
+
+このコマンドにより、Rプロジェクト配下のファイルに新たなライブラリが使われていたら、`renv.lock`に書き込んでくれる。変更がない場合は、以下のようなメッセージがでる
+
+```R
+> renv::snapshot()
+* The lockfile is already up to date.
+```
+
+たとえば、新たに`tidyr`パッケージを使うために、`install.packages("tidyr")` と実行する。global cacheにすでに存在する場合は、そこへのリンクを貼ってくれるだけなのですぐに完了する
+
+```R
+> install.packages("tidyr")
+Installing tidyr [0.8.3] ...
+ OK (linked cache)
+* Lockfile written to '~/renv-sandbox/renv.lock'.
+```
+
+`library(tidyr)`と新たに.Rファイルに追加してから実行すると、再度snapshotを実行すると、`tidyr`が使われていることを`renv`が発見してくれて、`renv.lock`に書き込んでくれる。
+
+```R
+> renv::snapshot()
+The following package(s) will be added to the lockfile:
+ _
+ tidyr [0.8.3]
+
+Do you want to proceed? [y/N]:
+```
+
+この辺の発見ロジックは、https://github.com/rstudio/renv/blob/master/R/dependencies.R#L488-L494 あたりの`renv::dependecies()`あたりにより実現されていると思われる。
+
+(つい先日 `pacman::p_load()` が `renv::dependecies()`に対応していないIssueをあげたのですが、翌日には対応してくれるほどのスピード感だったので驚いた : https://github.com/rstudio/renv/issues/143 )
+
+### ```renv::restore()```
+
+別のマシンやCIからRプロジェクトと同じパッケージをインストールするときに使う。基本的に`renv.lock`ファイルさえあれば動くので、Gitで`renv.lock`を管理しておけばどこからでも同じ環境が再現しやすい。
+
+今のところ自分はDocker ImageやCIのまっさらな環境に、`renv::restore()`させてから、Testさせるときに使っている
+
+```R
+> renv::restore()
+The following package(s) will be installed:
+ _
+ BH [1.69.0-1]
+ R6 [2.4.0]
+ RColorBrewer [1.1-2]
+<snip>
+Do you want to proceed? [y/N]: y
+<snip>
+```
+
+## その他コマンド
+
+### ```renv::status()```
+
+renvによるパッケージの管理状態を知るコマンド(といってもあまり使わない)
+
+```R
+> renv::status()
+* The project is already synchronized with the lockfile.
+```
+
+### ```renv::dependencies()```
+
+プロジェクトにあるソースとパッケージの関係を出力。おそらく、`renv::snapshot()`等で使われる
+
+```R
+> renv::dependencies()
+Finding R package dependencies ... Done!
+ Source Package Require Version
+1 /home/ooki/renv-sandbox/analysis.R dplyr
+2 /home/ooki/renv-sandbox/analysis.R ggplot2
+3 /home/ooki/renv-sandbox/analysis.R tidyr
+4 /home/ooki/renv-sandbox/script.R remotes
+5 /home/ooki/renv-sandbox/script.R renv
+```
+
+### `renv::hydrate()`
+
+ProjectのなかでSystem libraryから使われているPackageをprivate R libraryにインストールしてくれる。`renv::init()` の中でこれが実行されている模様
+
+```R
+> renv::hydrate()
+```
+
+### `renv::clean()`
+
+使ってないライブラリをPrivate R libraryからRemoveしてくれる。たまにお掃除したくなったときに使う
+
+```R
+> renv::clean()
+```
+
+### renv::settings$ignored.packages()
+
+renv管理から無視するパッケージ(testやdevtoolsなどが該当するかと思う)を設定する
+参考 : https://rstudio.github.io/renv/reference/settings.html
+
+```R
+> renv::settings$ignored.packages()
+character(0)
+> renv::settings$ignored.packages("devtools", persist = FALSE)
+> renv::settings$ignored.packages()
+[1] "devtools"
+```
+
+### `renv::settings$use.cache(FALSE)`
+
+renvのglobal cacheを使わなくする
+
+### `renv::settings$snapshot.type("simple")`
+
+renvのsnapshotの方法を変更する。デフォルトは`packrat`。`simple`にしたら、もとのRのユーザライブラリのすべてを`renv.lock`に書き込もうとするようになる
+
+## 今後
+
+今のところ、version 0.7でCRANに登録予定。また、1.0に向けて実装は日々進んでいるので、今後も楽しみである。`Packrat`はあまり周りで使ってる人はいなかったが、`renv`は使い勝手といい、分析の再現可能性担保のためにも流行ってほしいなと個人的には思っているので、ぜひみんな使っていってほしい
+
+参考 : https://github.com/rstudio/renv/issues/115
+