釣り臭あるタイトルだが、あるスクリプトに必要なライブラリに対し、ローカルに保存してあれば読み込み、なければinstall.packagesを実行する関数を作った。(というか調べた)
ライブラリを読みこむのにはlibraryとrequireがあるが、下記のように吐いてくる値が違う。
script.R
> print(library(hoge)) # => ライブラリが見つからないと処理が止まってしまう!
library(hoge) でエラー: ‘hoge’ という名前のパッケージはありません
> print(require(hoge)) # => ライブラリが見つからないとFALSEを返す!
要求されたパッケージ hoge をロード中です
[1] FALSE
これを利用して、require(hoge)がFALSEならinstall.packagesで該当パッケージをインストールしてrequireすれば良いのだが、ライブラリ名をベクトルに詰めてこんな感じでよしなに処理しようとすると、盛大にエラーを吐く。
gomi.R
> for(lib in libraries){
+ if(!require(lib)){
+ install.packages(lib)
+ require(lib)
+ }
+ }
要求されたパッケージ lib をロード中です
Error in install.packages : Updating loaded packages
c(" 要求されたパッケージ eval をロード中です ", " 要求されたパッケージ lib をロード中です ")
Failed with error: ‘ 'package' は長さ 1 でなければなりません ’
要求されたパッケージ lib をロード中です
Installing package into ‘/Users/01010357/Library/R/3.2/library’
(as ‘lib’ is unspecified)
これはrequireやlibraryはオブジェクトも文字列も受け取ることができるため。
libにライブラリ名が詰まっているが、requireはlibパッケージを読み込もうとしてしまう。
なので、install.packagesにベクトルをもたせられる事を利用し、下のコードみたいに読み込むといける
install.packages.R
load.libs <- function(lib){
lib.not.in.local <- lib[!(lib %in% installed.packages()[, "Package"])]
if (length(lib.not.in.local))
install.packages(lib.not.in.local, dependencies = TRUE)
sapply(lib, require, character.only = TRUE)
}
load.libs(libraries)
めっちゃ楽になった。