例題22-1:それってRでいいよね(暴言)

A: さて、Sも帰ったことだし今日の話題だが…

B: あれっ? この前にずらーっと数十行にわたって繰り広げられた会話は? S先生との会話で繰り広げられたぼくの目覚ましい大活躍は??

A: とてつもない醜態の間違いじゃないのか。もしくは目覚ましい胃袋か。

B: ちょ、会話が消されてるのにAさんがそんなこと言ったら皆そんなことがあったのかと思うじゃないですか! せっかくS先生がいろいろ話していったのに!

A: B君はひたすら東京土産のバウムクーヘン喰ってただけだろ。ま、Sの悪い持病で話が真っ暗な方向へ進んでしまったので私の判断で自主規制だ。Sはやっぱりパーソナリティに問題があるよな。

B: お土産を買ってきてくれる人に悪い人はいません! Aさんこそお土産を買ってきてくれる人を悪く言うなんて人として問題があります。

A: お土産しか判断基準がないのかよ。ま、Sが言ってたことで差しさわりないことだけ書いておくと、まずSはPython関連の情報発信がこの「Pythonで心理実験」だけでは不十分と考えているようだ。特に、 プログラミングに関する知識や経験がほとんどない人がPsychoPyを始めたい時に勧められるコンテンツが事実上ない ことを痛く気にしているらしい。

B: えー、例題18とかあるじゃないですかー。

A: ある程度経験ある人向けならともかく、初めての人にはダメだろ。何よりいきなり例題18から読めってのがダメすぎる。やはり初心者が一番最初のページから読み始められるように書いてないと。

B: えっ、それじゃこのコーナー書き直し? Aさんもぼくもリストラ?!

A: 白々しい演技をするな。Sはそんなこと言ってなかったろ。他にもwebという媒体自体にも いろいろ 限界を感じているとかで、PsychoPy Builderの本を書こうとしたりとか、Pythonのいろいろなパッケージを紹介する論文を書こうとしたりとかしているらしい。

B: へえ。限界って何でしょうね? あと本とか論文とかって気になるなあ♪

A: だーかーらー、さっきその話をしていて 真っ暗 な展開になったんだろーが! わざと蒸し返してるな?

B: へへへ。

A: その辺の話はパス! とにかく今日は、Sが置いて行った没ネタの供養ということでRPy2を取り上げる。RPy2はPythonからRを直接呼び出してしまおうという極悪系パッケージの一つである。

B: 極悪「系」って、ほかにも仲間がいるんですか。

A: (無視して)Rは統計処理のソフトウェアとして何を使おうかと調べたことがある人ならまず間違いなく聞いたことがあるだろう有名オープンソースソフトウェアだ。

B: ずいぶん微妙な限定の仕方だな…

A: Pythonと同じようにインタプリタからぺしぺしとコマンドを打ち込んで使うこともできるし、スクリプトを書いてがっつり処理を行うこともできる。Pythonとの違いはなんといっても強力な統計処理関数のラインナップ。PythonでもSciPyとかを入れればt検定とか繰り返しのない分散分析とか非線形回帰とかくらいなら出来るけど、Rはもっともっといろんなことが出来る。

B: もっともっとって、どんなことですか。

A: いろいろだよっ、い、ろ、い、ろ! Rの解説なんて私がやんなくても山のように解説があるんだから存分に検索したまえ。とにかく、そんな強力なRの機能をPythonから存分に利用してやろうというのがRPy2なのである。

B: 毎度のことながらほんっとに酷い解説だ。

A: RPy2の入手先はhttp://rpy.sourceforge.net/。pipな人はpip install rpy2でOK。

B: んん? RPy2なのにURLはrpyなんですね。

A: 私も昔のことはよく知らんのだが、RPyというパッケージが大幅にリメイクされてRPy2になったと聞いておるぞよ。数年前に私が初めてRPyを試した時には初代RPyのページもsourceforgeのサイトに残っていたんだが、今はリンクが切れているようだな。一時的なものかどうかわからんが。

B: これじゃないですか? http://rpy.sourceforge.net/legacy/

A: あ、ごめん。リンクがあったか。ま、ともかくそんなわけで2なのだ。

B: あのー、このサイト、Downloadのリンクがないんですけど、そのpipとかゆーのを使わないとインストール出来なんですか?

A: 詳しくは上記のサイトで公開されているドキュメントのインストールの項を見て欲しいんだが( http://rpy.sourceforge.net/rpy2/doc-2.4/html/overview.html#installation )、Windowsには非公式のコンパイル済みパッケージがあるようだが、Rのバージョンが指定されているし面倒くさそうな印象。

B: 印象って、あーた。試してないんですか?

A: 「いや、まじで時間無いんよ、かんべんして」というSの置手紙ならある。察してやれ。

B: …(お土産をくれる人に悪い人はいないと宣言した手前何も言えない)

A: その点、DebianやUbuntuなんかにはpython-rpy2というパッケージがあるからsudo apt-get install python-rpy2で一発だな。依存関係にRが含まれているからRのインストールまで一気にやってくれる。

B: へっ、Rもインストールしないといけないんですか。

A: 当たり前である。ていうかRをインストールしなかったらいったいどうやってRの力を借りるつもりなのか。

B: え。えーっと、その、webから。

A: ははっ、それが出来りゃ面白いがRPy2が対応しているって聞いたことはないな。とにかく私が面倒くさいからUbuntu上のIPythonで動作確認した例を紹介する(注:Windowsへのインストールは最後に触れます)。まずはrpy2のrobjectsをimportする。いちいちタイプするのは面倒くさいのでこの講座にしては珍しくasを使ってRという名前で参照する。

In [1]: import rpy2.robjects as R

B: むは、いきなり始まった。メモメモ。

A: R.r、要するにrpy2.robjects.rをインターフェースとして、裏で実行されているRと連携をとることが出来る。[R]の関数はrのメソッドであるかのように呼び出せる。例えば[R]でベクトルを作るc( )は以下のように呼び出せる。

B: [R]ってなんでカッコつきなんですか?

A: rpy2.robjectsの別名のRとアプリケーションのRの区別がつかないだろ。アプリケーションとしてのRの方を[R]と書くことにしてみた。

B: 何も考えずにas Rなんてimportするから…。

A: ほっとけ。

In [2]: data = R.r.c(0,0.5,1.0,0.3,1,0.9,1.0,0.0,0.1)

A: 変数dataにはFloatVectorというオブジェクトが格納されている。これはRPy2が提供するオブジェクトで、通常のPythonのリストではない。

In [3]: data
Out[3]:

[0.000000, 0.500000, 1.000000, ..., 1.000000, 0.000000, 0.100000]

B: ふむふむ。

A: [R]の文法では、関数名などにピリオド( . )を含むことが出来る。例えばt検定を行うt.testなどがそうだ。このような関数を先ほどのc()のように呼びだそうとすると、R.r.t.testとなってしまって、Pythonの文法で解釈すると[R]のtという名前にアクセスしていることになってしまう。この問題を回避するためには、R.rを辞書オブジェクトであるかのように見立てて[ ]演算子でアクセスする。t.testの場合はR.r['t.test']と書くわけだ。もちろん先ほどのc( )もR.r['c']と書いて呼び出せる。

In [4]: print R.r['t.test'](data, mu=0.5)



        One Sample t-test



data:  c(0, 0.5, 1, 0.3, 1, 0.9, 1, 0, 0.1)

t = 0.2236, df = 8, p-value = 0.8287

alternative hypothesis: true mean is not equal to 0.5

95 percent confidence interval:

 0.1895745 0.8770921

sample estimates:

mean of x

0.5333333

B: おお、いきなりt検定が出来てしまった。

A: この例を見るとわかるように、R.rを通じて実行した[R]の関数の戻り値は、そのまま[R]の関数への引数として用いることが出来る。そして、引数muのように数値や文字列であれば直接Pythonから渡すことも出来る。

B: リストとかは渡せないんですか? R.r['t.test']([1.0,0.5,0.3,0.1],mu=0.5)みたいな。

A: 残念ながらそれはエラーになる。PythonのリストとRのベクトルでは格納できる値が違うからな。そりゃ自動的に変換はできないだろう。

B: ちなみにコレ、printを付けなかったらどうなるんですか?

A: [R]の戻り値を格納したListVectorというオブジェクトになる。はっきりいって見難いのでおすすめできない。

In [5]: R.r['t.test'](data, mu=0.5)
Out[5]:

[Float..., Float..., Float..., ..., StrVe..., StrVe..., StrVe...]
  statistic:

[0.223607]
  parameter:

[8.000000]
  p.value:

[0.828668]
  ...
  statistic:

[str]
  parameter:

[str]
  p.value:

[str]

B: ぶはっ、だめだこりゃ。

A: せっかくだから分散分析をしてみようか。もはや説明不要の心理学者の強い味方、ANOVA君( http://riseki.php.xdomain.jp/index.php?ANOVA%E5%90%9B )を呼び出してみよう。anovakun_461.txtをダウンロードしてデスクトップ(/home/foo/Desktop)に置いておく。

B: なんと、そんなことまでできるんですか!

A: そりゃもう、単にPythonをリモコンにして[R]を操作しているだけだかからな。ちなみにたまたまこの記事を書いている時の最新バージョンが4.6.1なだけで他のバージョンでも問題ない。

B:

A: ええと、まず[R]にとってもカレントディレクトリはどこなのかな、と。

In [6]: print R.r.getwd()
[1] "/home/foo"

B: /home/fooが[R]のカレントディレクトリということですね。こりゃ本当に遠隔操作だなあ。ということは当然、setwdも…

A: 当然である。

In [7]: print R.r.setwd('/home/foo/desktop')
[1] "/home/foo/desktop"

B: これでデスクトップにカレントディレクトリが移動しましたね。

A: [R]のsource関数を使ってANOVA君を読み込む。

In [8]: R.r.source('anovakun_461.txt')
Out[8]:

[SignatureTranslatedFunc..., Vector]
  value:

  visible:

[       0]

B: なんだかわけわかんない表示ですが読み込めたんですか。

A: 読み込めたんです。さて、動作確認するには分析対象のデータが必要だな。ぺろぺろっとでっちあげるか。ええと…

B: (…ぺろぺろっと?)

A: こんなもんでいいか。参加者間要因がひとつ、参加者内要因がひとつの2要因の計画で、どちらの要因も2水準だ。data.csvという名前で保存しておく。

group,pre,post
A,220.4,341.2
A,240.1,309.2
A,229.5,381.2
B,310.7,390.7
B,299.6,376.5
B,320.1,391.7

B: データ件数はこれだけですか?

A: たくさん用意するのは面倒くさいじゃん。このデータを[R]に読み込む。普通に[R]を使う時と同じようにread.table関数を使えばいい。

In [9]: aovdata = R.r['read.table']('data.csv',sep=',',header=R.r.T)

B: んー。header=R.r.Tというのは…。[R]ならheader=Tと書くところですよね。

A: ていねいに考えるんだ。この文は[R]の文ではなく、あくまでPythonの文である。で、PythonはTという語を知らない。だからheader=Tと書くと「Tなんか知らん」というエラーが返ってくる。最悪なのは偶然Python側でTという変数が使われていた場合で、Pythonは何食わぬ顔で変数Tの値を[R]に渡そうとする。

B: むむむ。それはまるでぼくのために仕掛けられている罠のようだ。

A: TがPythonの変数ではなく[R]の定数であることを教えてやるにはどうしたらいいか。 [R]の名前にはR.rを通じてアクセスできるのだから、R.r.Tと書けばよい 。これが結論。

B: なるほど。ふむふむ。

A: ちなみに変数aovdataの中身は[R]のデータフレームが格納されているはずなので、ちょっと覗いてみよう。あまり詳しく解説しないが、DataFrameというオブジェクトが格納されていて、その中にFactorVectorやFloatVectorというクラスのオブジェクトが格納されているのがわかる。

In [10]: aovdata
Out[10]:

[FactorVector, FloatVector, FloatVector]
  group:

[       1,        1,        1,        2,        2,        2]
  pre:

[220.400000, 240.100000, 229.500000, 310.700000, 299.600000, 320.100000]
  post:

[341.200000, 309.200000, 381.200000, 390.700000, 376.500000, 391.700000]

B: むむむ。難しくてよくわからないんですけど、理解しないとダメですか。

A: いや、どうでもいい(あっさり)。

B: なんでどーでもいいことをいちいち取り上げるんですか! 嫌がらせだ! 難しいことをしているんだと見せつけてるんだ!

A: どんな風に実装されているかを見たら面白いかなあと思って載せてみただけだが…。ほら、こういう実装を見てると心がウキウキするじゃん?

B: まったくこの変態は…。

A: さて、ここまで準備できれば後はANOVA君を実行するだけである。

In [11]: R.r.anovakun(aovdata, "AsB", 2, 2)

[ AsB-Type Design ]

This output was generated by anovakun 4.6.1 under R version 3.1.0.
It was executed on Tue Jul 15 15:49:17 2014.


<< DESCRIPTIVE STATISTICS >>

---------------------------------
  A   B   n      Mean     S.D.
---------------------------------
 a1  b1   3  230.0000   9.8595
 a1  b2   3  343.8667  36.0740
 a2  b1   3  310.1333  10.2617
 a2  b2   3  386.3000   8.5018
---------------------------------


<< SPHERICITY INDICES >>

== Mendoza's Multisample Sphericity Test and Epsilons ==
-----------------------------------------------------------------------

 Effect  Lambda  approx.Chi df       p         LB     GG     HF     CM
-----------------------------------------------------------------------
      B  0.0406      4.8063  1  0.0284 *   1.0000 1.0000 1.0000 1.0000
-----------------------------------------------------------------------
                             LB = lower.bound, GG = Greenhouse-Geisser
                             HF = Huynh-Feldt-Lecoutre, CM = Chi-Muller


<< ANOVA TABLE >>

-------------------------------------------------------------
    Source          SS  df          MS  F-ratio  p-value
-------------------------------------------------------------
         A  11266.9408   1  11266.9408  32.3654   0.0047 **
     s x A   1392.4667   4    348.1167
-------------------------------------------------------------
         B  27084.5008   1  27084.5008  61.5631   0.0014 **
     A x B   1065.9675   1   1065.9675   2.4229   0.1946 ns
 s x A x B   1759.7867   4    439.9467
-------------------------------------------------------------
     Total  42569.6625  11
                 +p < .10, *p < .05, **p < .01, ***p < .001


output is over --------------------///

Out[11]: rpy2.rinterface.NULL

B: あっさり出来ましたね。特に新たに注意すべきこともないような。

A: だな。Pythonから[R]を呼ぼうなんて人は、Pythonでデータの整理を済ませてPythonでは出来ない処理を[R]に投げるなんて人がほとんどだろう(独断&偏見)から、この程度のことを解説しときゃそれで充分なんじゃないかと。

B: えー。そうとは限んないじゃないですか。Aさんがそうだってだけじゃないんですか?

A: ま、本格的に使いたい人はRPy2のドキュメントを読んでいろいろ遊んでほしい。この解説では後はPythonとRPy2のデータの受け渡しのことを補足しておく。いちいちテキストファイルにデータを書きだしてやり取りするんだったら意味ないからな。

B: へえ、その辺の解説は必要だっていう自覚はあるんだ。

A: まず、RPy2からPythonへの変換。さっきのt検定と分散分析に使った変数をPythonのnumpy.ndarrayに変換してみる。numpy.asarrayが結構賢いので、それっぽく変換出来る。データフレームはもうちっと丁寧に変換してやった方がいいかもしれんが、まあここでは値が得られりゃいいや的なノリで。

In [12]: numpy.asarray(data)
Out[12]: array([ 0. ,  0.5,  1. ,  0.3,  1. ,  0.9,  1. ,  0. ,  0.1])

In [13]: numpy.asarray(aovdata)
Out[13]:
array([[   1. ,    1. ,    1. ,    2. ,    2. ,    2. ],
       [ 220.4,  240.1,  229.5,  310.7,  299.6,  320.1],
       [ 341.2,  309.2,  381.2,  390.7,  376.5,  391.7]])

B: 参加者間要因がA,Bではなく1,2になっているのが気になりますね。

A: んー。[R]でも内部ではFactorのラベルとインデックスが別になっているのだろうな。で、asarray()だとインデックスの方を変換しているのだろう。次はPythonからRPy2へ持っていく場合。持っていきたいのがベクトルならば、ほげほげVectorという関数が利用できる。これは[R]の関数ではなくrpy2.robjectsの関数なので、R.rから呼び出すのではなく、Rから直接呼び出す点に注意。

In [14]: R.FloatVector(range(10))
Out[14]:

[0.000000, 1.000000, 2.000000, ..., 7.000000, 8.000000, 9.000000]

In [15]: R.StrVector(range(10))
Out[15]:

[str, str, str, ..., str, str, str]

B: 最後のstr,str,str…ってちゃんと変換できているんですか。関数名からしてrange(10)の戻り値を文字列に変換しているんだから、"1","2","3",...ってのが得られるんですよね?

A: そういう時はとりあえずprintしてみるとよいぞよ。

In [16]: print R.StrVector(range(10))
 [1] "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"

B: むふふ、やっぱりぼくの予想通りだぞ。

A: データフレームを作るのはちょっと面倒くさいのでrpy2.rlike.containerというのを使う。実はこれは私もあんまりよく知らなくて、どっかで調べたヤツの受け売りである。

In [17]: import rpy2.rlike.container as rlc

In [18]: data = rlc.OrdDict([('group',R.StrVector(('A','A','A','B','B','B'))),
   ....:            ('pre',R.FloatVector((220.4,240.1,229.5,310.7,299.6,320.1))
),
   ....:            ('post',R.FloatVector((341.2,309.3,381.2,390.7,376.5,391.7)
))])

In [19]: dataframe = R.DataFrame(data)

B: これもどんなのが出来たのかわからないなあ。とりあえずprintすればよいんでしたっけ?

A: おk。

B: ではprint、と。

In [20]: print dataframe
  group   pre  post

1     A 220.4 341.2

2     A 240.1 309.3

3     A 229.5 381.2

4     B 310.7 390.7

5     B 299.6 376.5

6     B 320.1 391.7

B: おお、さっきread.tableした時よりもちゃんとした出力ですね。

A: そりゃさっきはprintしなかっただけだ。さっきのもprintすれば同じように整形された出力が得られる。

B: えっ、そうだったんですか。騙された。

A: 別に騙したつもりはないが。あまり深入りする気もないのでそろそろ終わりにしようと思うが、最後に「これぞリモコン!」というべきテクニックを紹介しておこう。最初の方でrを辞書オブジェクトのように見立てて[ ]演算子を適用することが出来る、と述べたが、rは本当に多芸なインターフェースで、関数のように見立てて( )を適用することも出来るのだ。そうした場合、 引数の文字列を[R]の文とみなして処理を実行する 。百聞は一見にしかず、ということで以下の例を見てみよう。一様変数からサンプルを得る関数runif()を使って10個のサンプルを得て、その平均値が0.5と異なると言えるかt検定を行っている。

In [21]: print R.r('results <- t.test(runif(10),mu=0.5)')


        One Sample t-test



data:  runif(10)

t = -1.1503, df = 9, p-value = 0.2797

alternative hypothesis: true mean is not equal to 0.5

95 percent confidence interval:

 0.2270547 0.5889311

sample estimates:

mean of x

0.4079929

B: こ、これは…。「results <-」って、[R]でいうところの変数resultsへの代入ですよね? 完全にRそのものじゃないですか。

A: もう[R]にコマンドを投げてるだけだからな。演算子をはじめとする文法はすべて[R]に従う。だから代入に <- も使えるし、なによりここで代入されている変数resultsは[R]の変数であって、Pythonの変数ではない!

B: え、どういうことですか?

A: Pythonの裏で[R]が実行されていて、変数resultsはその裏で走っている[R]に保存されている。だから、Pythonの側でresultsという変数にアクセスしようとしても「そんな変数はない」と言われる。すでに別の用途にresultsという変数を使っていたら、そっちの値が使われるだけのことだ。

B: むむむ。さっきのTと同じ話ですな。これは気を付けないと…

A: ややこしいか? 私には極めて明快に見えるがな。勝手にPythonとRの間でやりとりされるよりも、PythonはPython、RはRと分かれていた方が気持ちがいい。この変数resultsは[R]の側にあるのだから、当然[R]の側では使用することが出来る。ここまでの話が理解できていれば、次の文が理解できるはずである。

In [22]: print R.r['results']


        One Sample t-test



data:  runif(10)

t = -1.1503, df = 9, p-value = 0.2797

alternative hypothesis: true mean is not equal to 0.5

95 percent confidence interval:

 0.2270547 0.5889311

sample estimates:

mean of x

0.4079929

B: さっきのt検定の結果だ。ええと、実行しているのはprint R.r['results']で、( )じゃないから[R]への丸投げじゃない。rに[ ]がついているから、これは[R]の名前の参照。だから、…、…、あれ? そうか。さっきの「results <-」の代入で[R]にresultsという名前の変数が出来ているから、R.r['results']はその変数resultsへPythonの側からアクセスしているのか。

A: おお、ご名答。実は恐らくわからんだろうと踏んでいた。

B: ふふふ、甘く見てもらっては困りますな! いやあ、それにしてもRPy2、なかなかすごいじゃないですか。なんで今まで紹介しなかったんですか?

A: へ?そんなもん私が使わないからに決まっとる。今回はSが置いて行った没原稿の供養に取り上げただけで。

B: さっき「数年前に試した」って言いましたよね。試しても気に入らなかったと?

A: んー。なんちゅうのか 面倒くさい ねん。結局[R]の関数やらなんやらを熟知したうえで、そのうえでデータの変換とかしないといかんだろ。データの変換だけならまだしも、分析結果をPythonで受けて何か処理しようとしたらアタマがおかしくなりそうになる。例えばさっきのt検定の結果で、信頼区間の上限と下限の値をPythonの変数に持ち込んで何か処理を続行したいとする。どうすればいいかと言うと答えはこうだ。

In [23]: list(R.r['results'][3])
Out[23]: [0.22705465062338198, 0.5889311341959678]

B: なんだこれ。R.r['results'][3]の3ってどこから出てきたんですか。

A: そりゃもう[R]のt.test()の戻り値を確認して、4番目の要素に信頼区間の値が入っていることを確認したんさ。

B: list( )でくくってるのは?

A: listでもtupleでもnumpy.ndarrayでもいいんだけど、変換しておかないとPython側での扱いが面倒な形で格納されているのでこうしている。

B: …これってもしかして、「[R]のt.testの戻り値がこういうフォーマットであることを知っていないと書けない」系のコードですか。

A: 恐らくYes。

B: …「アタマがおかしくなりそうになるんじゃなくて、Aさんの頭が(自粛)なんじゃないんですか」って言おうと思ってたけど、これはぼくでも面倒くさく思うかも。

A: ま、printすれば普通に[R]で見るように見えるんだから、単にPythonを[R]のリモコンとして使うなら悪くないかな、と思う。あと、Rの関数が返すオブジェクトの構造をみっちりと調べ込んで、[R]をバックエンドに使うオリジナルの統計処理アプリケーションのインターフェース部分をPythonで作るってのも有りなのかな…と思わなくもない。私ぁ自分ではそんな面倒くさいもん絶っっっっ対に作らないけどな。

B: リモコンでも充分楽しそうだけどなあ。

A: リモコンするならPython側でデータフレームを扱える必要があるだろうなあ。さっき挙げた例みたいにちまちまとデータフレームを作成するのはいまいち嬉しくない。そこで…というわけでもないのだが、次回はこれまたSの没原稿の供養でpandasを取り上げる。予定。

B: パンダ?す?

A: 本が和訳されたりして今話題のPythonパッケージだ。他のサイトでよっぽど詳しく取り上げられているので要らんのじゃないかな、と思うけどまあ一応、簡単にさわりだけ説明するつもりだ。ではでは、続きます。

補足1

作者です。Aに言いたい放題言われてむかついたのでWindows7で動かしました。Windows7はx64、Pythonは32bitの2.7を使っています。

本文中に挙げたrpy2のサイト( http://rpy.sourceforge.net/ )のdocumentationの Download に書かれているように、非公式のWindows用コンパイル済みrpy2がUnofficial Windows Binaries for Python Extension Packages( http://www.lfd.uci.edu/~gohlke/pythonlibs/ )で配布されています。この記事を書いている2014年7月現在、R3.1.0に対応したrpy2-2.4.2がダウンロードできます。

rpy2をインストールする前に、Rをインストールしておきましょう。コンパイル済みrpy2がR3.1.0を対象にコンパイルされているので、R3.1.0をインストールしてください(この記事を書いている時点で最新版は3.1.1)。バージョンが一致しないと動かないかもしれません。ここではC:\Program Files\R\R-3.1.0に32bit版と64bit版の両方をインストールしたとします。

インストールが済んだら、環境変数に以下の変更を加えてください。筆者はシステム環境変数に登録して動作することを確認しましたが、ユーザー環境変数でもいけるかもしれません。ドキュメントを読む限りPATHが通っているかR_HOMEが設定されているかのどちらかが満たされていれば使えるような気がするのですが、なかなか動かなくてあれこれいじりまわして動いた時の設定が以下のものです。

  • PATHにC:\Program Files\R\R-3.1.0\bin\i386を追加

  • R_HOMEという項目を追加してC:\Program Files\R\R-3.1.0と入力

  • R_USERという項目を追加してにWindowsのログインユーザー名を入力

設定が済んだら、先ほどのサイトからrpy2-2.4.2.win32-py2.7.exeをダウンロードしてインストールします。インストール終了後、PythonインタプリタやIPythonを起動してimport rpy2.robjectsしてみてください。エラーなしにimport出来れば恐らく今回のサンプルは動作します。

補足2

Windows上でのR_HOME関連の挙動が納得がいかなかったのでちょっとrpy2のソースを読みました。バージョンはUnofficial installerのrpy2-2.4.2-py2.7です。

R_HOMEはまず環境変数(os.environ)を確認し、定義されていなければレジストリのHKEY_LOCAL_MACHINE\Software\R-core\Rからインストールディレクトリを取得しようとします。環境変数からR_HOMEが得られず、レジストリからの取得にも失敗すると"No environment variable R_HOME could be found, ...(以下略)"というエラーがraiseされます。

R_HOMEが得られたら、続いてplatform.architecture()[0]を確認し、32bitであれば'i386'、64bitであれば'x64'を変数_win_bindirを設定します。続いてos.envirion['PATH']にos.path.join(R_HOME, 'bin', _win_bindir)、os.path.join(R_HOME, 'modules', _win_bindir)、os.path.join(R_HOME, 'lib')を追加します。そして、for文で変数r_dirに'bin'、'lib'を代入しながらRlib = os.path.join(R_HOME, r_dir, _win_bindir, 'R.dll')、win32api.LoadLibrary( Rlib )を実行します。for文を終えた時点でLoadLibrary(Rlib)の実行に成功していなければ、"Unable to locate R.dll within %s" % R_HOMEというエラーがraiseされます。

結論として、32bitのPythonには32bitのR、64bitのPythonには64bitのRが必要です。そして、環境変数R_HOMEはその中のbin/i386やlib/i386(64bit版ならbin/x64やlib/x64)にR.dllがインストールされているディレクトリでなければいけません。