Stan のデータを R にエレガントに取り込む


Stan で解析するデータを R に取り込むことを考えてみます。 Stan のデータは R 中に直接記述しても良いのですが,独立したファイルに記述した方が自由度が高くて良いでしょう。コマンドラインからも利用できるようになります。

Stan 用のデータは R とほぼ同じ文法で書くことができます[A]。拡張子は一般的に *.data.R が利用されます。

N <- 6
x <- c(0.1, 1.2, 2.3, 3.4, 4.5, 5.6)
y <- c(1.3, 3.4, 4.1, 5.9, 5.5, 7.2)

R のコードですから, R から呼び出すのは容易です。普通なら以下のように source 関数を使うでしょうか。

source("stan_data.data.R")

ここで問題が発生する可能性があります。具体的には,変数の名前が衝突してしまう恐れがあります。短いコードなら大丈夫かもしれませんが, Stan のモデルの変数名で R の使える変数名が制限されてしまうのは気持ちの良いものではありません。そして,読み込んだ変数を stan 関数から利用するためにリストにするのも面倒です。

data <- list(N=N, x=x, y=y)

これらの問題を一気に解決する方法があります。それは sys.source 関数により新しい環境にデータを読み込ませる方法です。具体的には次のようにします。

data <- new.env()
sys.source("stan_data.data.R", data)

これで data 変数にデータが読み込まれます。 data は環境オブジェクトの変数ですが, stan 関数は幸い環境オブジェクトでも受け取ってくれますし,リストに変換したければ as.list 関数をかませるだけです。

関数にすると次のような感じになると思います。

load_stan_data <- function(name, file, envir=as.environment(-1L), parent=envir, type=c("environment", "list")) {
   name <- deparse(substitute(name))
   envir <- envir  # forces evaluation
   parent <- parent  # same as above
   type <- match.arg(type)
   hash <- new.env(parent=parent)
   sys.source(file, hash)
   assign(name, switch(type, list=as.list(hash), environment=hash), envir=envir)
}

3, 4 行目は遅延評価対策です[B]

以下のように使うことができます。

load_stan_data(data, "stan_data.data.R")

[2013-10:22 21:00 追記] Gist に公開しました

脚注

  1. 詳しくはマニュアルを参照。 []
  2. 遅延評価対策のために force という関数があるのですが,環境を得るのでここでは使えません。 []