Rpy2の使い方の備忘録

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

[公式ページ](https://rpy2.bitbucket.io/)より引用。
>rpy2 is an interface to R running embedded in a Python process.
The project is mature, stable, documented, and widely used (older documentation).

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

- [Pythonからよく使うRの統計関数を簡単に呼び出せるようにしてみた (多重比較・Rpy2)](https://qiita.com/MTNakata/items/129d334cea397a6ec0c3)
- [rpy2_wrapperを使ってPythonコードで統計検定（TukeyHSD・Dunnett・Steel-Dwassなど)](https://qiita.com/MTNakata/items/9c80070158fbe90afdd3)

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

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

#Rpy2の使い方

公式ページを参考に。

[Introduction to rpy2](http://rpy2.readthedocs.io/en/version_2.8.x/introduction.html)

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

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

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

```python
result = ro.r("2")
print(result)
# [1] 2
```

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

```python
print(type(result))
# <class 'rpy2.robjects.vectors.FloatVector'>
```
数値のみを取り出したい場合は以下のように要素を指定します。

```python
print(result[0])
# 2.0
```
数式でも同様に`ro.r`で実行できます。

```python
result = ro.r("2 + 2")
print(result[0])
# 4.0
```
`ro.r`の中で行ったRの変数代入は、その後に実行する`ro.r`の中でも引き継がれます。以下の例の"a"のような感じ。

```python
ro.r("a <- 2")
print(ro.r("a * 2")[0])
# 4.0
```

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

```python
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の関数を使う場合、主に２つの方法があります。

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

```python
ro.r("a <- c(1,50,4,7,10,3)")
ro.r("mean(a)")[0]
# 12.5
```

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

```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で定義した変数を渡します。

```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`です。

```python
from rpy2.robjects.packages import importr
multcomp = importr("multcomp")
```
呼び出したパッケージの関数は、以下の３つのいずれでも利用可能なようです。

- ro.r("関数名")
- ro.r["関数名"]
- multcomp.関数名

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

注：パッケージのインストールはあらかじめ、コマンドラインのRの方で行っておくのがラクです。（[参考ページ](https://qiita.com/MTNakata/items/129d334cea397a6ec0c3)）

##NumPy, Pandas <-> R

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

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

やり方は以下の通り。

###NumPy <-> R

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

```python
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のアレイに変換されるようになります。

```python
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と似ているので覚えやすい。

```python
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>
<img width="232" alt="Table.png" src="https://qiita-image-store.s3.amazonaws.com/0/204284/b5f49a6e-3baf-cd95-0ef9-abb601ddcf97.png">

##小ネタ

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

以上です。