Python から R を使うには、古くは PypeR(パイパー)というライブラリがありましたが、開発が止まっているようです。ここでは rpy2 を使う方法を説明します。rpy2 は pip install rpy2
でインストールできます。詳しい使い方はドキュメントを見ればいいのですが、以下に簡単な使い方をまとめておきます。
from rpy2 import robjects # Rを起動 print(robjects.r("x = 123"))
[1] 123
print(robjects.r("x * 2"))
[1] 246
複数行からなるプログラムは次のように打ち込みます:
print(robjects.r(''' x = 123 x * 2 '''))
[1] 246
Python で print()
する前のオブジェクトを保存しておくと便利です:
res = robjects.r("binom.test(2, 10)") print(res)
Exact binomial test data: 2 and 10 number of successes = 2, number of trials = 10, p-value = 0.1094 alternative hypothesis: true probability of success is not equal to 0.5 95 percent confidence interval: 0.02521073 0.55609546 sample estimates: probability of success 0.2
個々の正確な値は res
の要素として取り出せます:
res[2][0]
0.10937499999999994
res[3][0], res[3][1]
(0.025210726326833365, 0.5560954623076414)
R の関数オブジェクトを Python 側に持ってくることもできます:
rbinomtest = robjects.r["binom.test"] print(rbinomtest(2, 10))
Exact binomial test data: 2L and 10L number of successes = 2, number of trials = 10, p-value = 0.1094 alternative hypothesis: true probability of success is not equal to 0.5 95 percent confidence interval: 0.02521073 0.55609546 sample estimates: probability of success 0.2
行列を R に送る例です:
v = robjects.IntVector([3, 1, 2, 4]) # FloatVectorでも可 m = robjects.r["matrix"](v, nrow=2) robjects.globalenv["m"] = m res = robjects.r("fisher.test(m)") # 前2行は res = robjects.r["fisher.test"](m) でもよい print(res)
Fisher's Exact Test for Count Data data: m p-value = 0.5238 alternative hypothesis: true odds ratio is not equal to 1 95 percent confidence interval: 0.218046 390.562917 sample estimates: odds ratio 4.918388
Python と R で結果を比較してみます:
import numpy as np from scipy import stats from rpy2 import robjects rng = np.random.default_rng() fisher_test = robjects.r['fisher.test'] x = 0 for i in range(10000): a = rng.integers(0, 30, 4) m = a.reshape(2, 2) p_scipy = stats.fisher_exact(m).pvalue # scipyによるp値 m_r = robjects.r.matrix(robjects.IntVector(a), nrow=2) res = fisher_test(m_r) p_r = res[0][0] # Rによるp値 e = abs(p_scipy - p_r) if e > x: print(e, p_scipy, p_r, a) x = e
同様なことをBarnard検定でもやってみます。Rの exact.test()
に to.plot=FALSE
というオプションも与えたいのですが、Pythonからは to_plot=False
のように指定します:
robjects.r("library(Exact)") exact_test = robjects.r['exact.test'] def compare(): a = rng.integers(1, 30, 4) m = a.reshape(2, 2) p_scipy = stats.barnard_exact(m).pvalue m_r = robjects.r.matrix(robjects.IntVector(a), nrow=2) res = exact_test(m_r, to_plot=False) p_r = res[2][0] return p_scipy - p_r r = [compare() for _ in range(1000)]
r
の分布を調べてみてください(このスレッド、このissue参照)。
Last modified: