Posted at

Rpy2の使い方の備忘録

More than 1 year has passed since last update.

Rpy2を使うと、PythonからRを利用できます。

公式ページより引用。


rpy2 is an interface to R running embedded in a Python process.

The project is mature, stable, documented, and widely used (older documentation).


Rpy2に関連した前回までの記事は以下の通り。

Rpy2の環境構築手順については、1つ目の記事を参照のこと。

今回は、Rpy2の使い方について、今のところ把握している範囲のみご紹介します。


Rpy2の使い方

公式ページを参考に。

Introduction to rpy2


rpy2.robjects.rを使ってRの関数を実行

まず、rpy2.robjectsをインポートします。

import rpy2.robjects as ro

ro.rの引数に、Rで実行したい内容を文字列で渡します。

result = ro.r("2")

print(result)
# [1] 2

ro.rに数値を渡した場合、ベクトルになる点に注意。

print(type(result))

# <class 'rpy2.robjects.vectors.FloatVector'>

数値のみを取り出したい場合は以下のように要素を指定します。

print(result[0])

# 2.0

数式でも同様にro.rで実行できます。

result = ro.r("2 + 2")

print(result[0])
# 4.0

ro.rの中で行ったRの変数代入は、その後に実行するro.rの中でも引き継がれます。以下の例の"a"のような感じ。

ro.r("a <- 2")

print(ro.r("a * 2")[0])
# 4.0

数列は以下のように入力します。

r_array = ro.r("c(1,50,4,7,10,3)")

print(r_array)
# [1] 1 50 4 7 10 3

このように、ro.rがRpy2の基本機能になります。


rpy2.robjectsでRの関数を使う(mean()を例に)

Rの関数を使う場合、主に2つの方法があります。

1つ目は、前述のro.rで代入した変数に対して、ro.r内で処理する方法です。

ro.r("a <- c(1,50,4,7,10,3)")

ro.r("mean(a)")[0]
# 12.5

2つ目は、関数をオブジェクトとしてpythonの変数に代入し、その変数を関数として扱う方法です。

result = ro.r("c(1,50,4,7,10,3)")

mean = ro.r["mean"]
mean(result)[0]
# 12.5

1つ目の方はRそのままなので楽です。2つ目の方はPythonっぽい書き方ですね。


Pythonで定義した変数をro.rで使えるようにする

ro.r.assign()を使うとPythonで定義した変数をro.r内の変数として引き渡すことができます。

ro.r.assign()の1つ目の引数に引き渡し先のro.r内の変数、2つ目の引数にPythonで定義した変数を渡します。

a = 1

ro.r.assign("a", a)
print(ro.r("a")[0])
# 1
print(ro.r("a * 2")[0])
# 2.0

この機能は地味に便利です。


Rのパッケージの呼び出し方

Rのパッケージを呼び出すlibrary(r_package)に相当するRpy2の機能はrpy2.robjects.packages.importrです。

from rpy2.robjects.packages import importr

multcomp = importr("multcomp")

呼び出したパッケージの関数は、以下の3つのいずれでも利用可能なようです。


  • ro.r("関数名")

  • ro.r["関数名"]

  • multcomp.関数名

パッケージごとの使い方の違いなどはまだ把握できていません。

注:パッケージのインストールはあらかじめ、コマンドラインのRの方で行っておくのがラクです。(参考ページ


NumPy, Pandas <-> R

個人的な意見ですが、Rpy2のもっとも素晴らしいところは、NumPyやPandas形式のデータが簡単に利用できるところだと思っています。

Rに慣れていないと、Rのアレイやデータフレームの取り扱いは地味に苦痛です。Rpy2のこの機能を使えば、NumPyやPandasでデータ整理を行った後に、Rにデータを渡してそのまま解析することが可能です。これは、Pythonユーザーの私にとってはめちゃ快適です。

やり方は以下の通り。


NumPy <-> R

NumpyからRへの変換にはnumpy2ri.py2ri()を使います。

import numpy as np

from rpy2.robjects import numpy2ri

py_array = np.array([[1,4,3,6,3],[1,5,3,4,10]])
ro.r.assign("r_array",numpy2ri.py2ri(py_array))
print(ro.r("r_array"))

# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 4 3 6 3
# [2,] 1 5 3 4 10

numpy2ri.activate()を実行するとRのアレイが自動的にNumpyのアレイに変換されるようになります。

numpy2ri.activate() #numpy<->Rをアクティブに


r_array = ro.r("c(1,50,4,7,10,3)")
print(r_array)
# [ 1. 50. 4. 7. 10. 3.]

print(type(r_array))
# <class 'numpy.ndarray'>


Pandas <-> R

Pandasの場合は、pandas2ri.activate()pandas2ri.py2ri()を使います。NumPyと似ているので覚えやすい。

import pandas as pd

from rpy2.robjects import pandas2ri
pandas2ri.activate()
py_df = pd.DataFrame(py_array)
r_df = ro.r.assign("r_df",pandas2ri.py2ri(py_df))
r_df

R/rpy2 DataFrame (2 x 5)




Table.png


小ネタ

ro.rの引数として渡すRのコードはダブルクオーテーション""で囲っています。もし、Rの関数内でもクオーテーションを使う必要がある場合には、シングルクオーテーション''とダブルクオーテーション""で使い分ける必要があります。

以上です。