Jupyterで1つのノートブック内にRとPythonを共存させる

　　
これは<a href="https://qiita.com/advent-calendar/2017/jupyter">Jupyter Advent Calendar 2017</a>の11日目の記事です。
この記事では、「Rはそれなりに触ってきたけど、Pythonはまだ学習中で思い通りにコードが書けない」という人[^1]や「Pythonを使わなきゃいけないような状況でも執念でRを使いたい」という人[^2]向けに、「特定の処理のみをPythonに任せて、基本的なデータ処理はRでやる」方法について、簡単に紹介したいと思います。[^3]

[^1]: 私のことです
[^2]: 私のことです
[^3]: 正直、複数人での分析をする場合や処理過程のレビューをしてもらう仕組みがある場合などは、このやり方はやめたほうが良いと思います。個人でやっているものやアドホックでサクッと出すデータくらいのときに使うと良さそうです。

## なぜRとPythonを共存させたいのか
私は、業務&趣味で、データ分析や可視化をするときにJupyterを利用しています。元々、RStudioを利用していたのですが、最近はPythonを書くことが増えてきた＆処理過程や結果を共有しやすいなどの理由から、Jupyterを使うことが多くなってきました。

しかし、元々R(RStudio)を使っていた自分にとっては、以下のような点から微妙に使いにくさを感じていました。
<ul>
<li>一部の処理についてはRの方が早く楽に書ける</li><li>しかし、Rのカーネルを選ぶとPythonのipywidgetsなどが使えない</li><li>逆もまた然り…</li>
</ul>

このような使いにくさを解消するために何か良い方法ないかなーと調べていたら、それっぽいやり方を見つけたので、その方法を簡単に紹介したいと思います。

## なにをやったのか

元々、Jupyter Notebook内にShinyをねじ込んでインタラクティブなダッシュボードを用意したかったのですが、結構大変そうだったので、方針を変えてPythonとRを一つのノートブック内に共存させて、「Rで前処理などをしつつ、可視化などの部分でのみPythonを書く」という方法で対処することにしました。

実際には、以下のような流れでやりました。

<ol>
<li>PythonからRを呼び出すためのパッケージをインストール</li>
<li>マジックコマンドでRを呼び出してデータ処理、その後Pythonに渡す</li>
<li>ipywidgetsなどでインタラクティブな可視化</li>
<li>nbdashboardでそれっぽく見せる</li>
</ol>

ipywidgetsやnbdashboardに関しては他の方が分かりやすい記事をたくさん書かれているので、今回は1と2の話をしたいと思います。

## 実行環境
<ul>
<li>macOS Sierra</li><li>anaconda3-4.4.0 (Python3.6)</li><li>conda 4.3.30</li><li>Jupyter 4.3.0</li>
</ul>

という感じです。基本的にanacondaの中にあります。
## パッケージのインストール
PythonからRを使うための<a href="https://rpy2.bitbucket.io/">rpy2</a>というパッケージがあるので、こちらをインストールします。
基本的にrpy2を入れれば、あとは楽に進みます。rpy2のインストールも楽です。
以下でいけます。



<div class="highlight"><pre><span></span>conda install rpy2</pre></div>

ちなみに、↑を実行すると、この辺がインストールされるようです。

```
The following NEW packages will be INSTALLED:

    cairo:        1.14.8-0
    fontconfig:   2.12.1-3
    gettext:      0.19.8.1-hb0f4f8b_2
    glib:         2.50.2-1
    gsl:          2.2.1-h002c638_3
    harfbuzz:     0.9.39-2
    krb5:         1.14.2-hc0fd8ed_4
    libedit:      3.1-hb4e282d_0
    libffi:       3.2.1-h475c297_4
    libssh2:      1.8.0-h1218725_2
    ncurses:      6.0-hd04f020_2
    pango:        1.40.3-1
    pcre:         8.39-1
    pixman:       0.34.0-hca0a616_3
    r-assertthat: 0.2.0-r342hacfac53_0
    r-base:       3.4.2-hc151561_0
    r-bh:         1.65.0_1-r342hc3f23d0_0
    r-bindr:      0.1-r342hb4d41c9_0
    r-bindrcpp:   0.2-r342h94b3c25_0
    r-bit:        1.1_12-r342hf8cc2cf_0
    r-bit64:      0.9_7-r342h1cba8d6_0
    r-blob:       1.1.0-r342h4b1ee69_0
    r-dbi:        0.7-r342h6aefa47_0
    r-dbplyr:     1.1.0-r342h9881601_0
    r-digest:     0.6.12-r342h7ffa501_0
    r-dplyr:      0.7.4-r342hd462e57_0
    r-glue:       1.1.1-r342hfa53b3f_0
    r-magrittr:   1.5-r342hc800aed_4
    r-memoise:    1.1.0-r342h0d1069b_0
    r-pkgconfig:  2.0.1-r342h037cecb_0
    r-plogr:      0.1_1-r342he1be899_0
    r-purrr:      0.2.3-r342h7646bf1_0
    r-r6:         2.2.2-r342hd083555_0
    r-rcpp:       0.12.13-r342hd23d99a_0
    r-rlang:      0.1.2-r342h6f7de11_0
    r-rsqlite:    2.0-r342h13ed314_0
    r-tibble:     1.3.4-r342h9aabc0a_0
    rpy2:         2.9.0-py36r342h301bfa9_0
```

anacondaの下に改めて別のRを入れる感じになるんですかね。
デフォルトで入れているっぽいパッケージに若干物足りなさを感じますが、今回はひとまず気にしないでおきましょう…(tidyverseで入れてくれればいいのに)。

## マジックコマンドでRを呼び出してデータ処理

先ほどインストールしたrpy2をJupyterのNotebook上で使えるように、コードセル内にマジックコマンドを記述する必要があります。
こちらも単純で、以下でいけます。

```python

%load_ext rpy2.ipython
```

ただし、↑を実行すると、`_rinterface.cpython-36m-darwin.so requires version 9.0.0 or later, but libiconv.2.dylib provides version 8.0.0`みたいなエラーが返ってきて上手くいかないパターンもあるようです。
そんなときは、以下のような感じでバージョンが合っていないやつをアップデートしてあげれば上手くいくはずです。

```
conda update libiconv
```

さて、Rでデータ処理をしてみましょう。
先ほどの`%load_ext`で読み込んだら、あとは同一ノートブック内に`%R`に続けてRのコードを書けます。雰囲気はこんな感じです。(中身はかなりテキトーに書いてます…)


```python
import pandas as pd
import numpy as np

pydata = pd.DataFrame(np.random.randn(10,3), columns=['a','b','value'])

# ここからR
%load_ext rpy2.ipython

%R require(dplyr)

# 自分でデータフレームを作成したり…
%R data <- data.frame(hoge, fuga, piyo)
%R group_data <- data %>% group_by(piyo) %>% summarise_all(funs(mean))

# Python側で用意したデータをRに渡すこともできたりします(-iでインプット)
%R -i pydata
%R join_data <- data %>% left_join(pydata, by=c("hoge"="a"))

# R側で処理したデータをPythonに渡すときも簡単(-oでアウトプット)
%R -o join_data

```


例えば、irisをSpeciesごとにグルーピングして平均をとるという処理をしたあと、`%R -o data`とすることで、R側で処理をおこなったデータフレームがPython側のオブジェクトとして利用できるようになっていることがわかると思います(%Rが頭にないところは、Pythonのコードになります)。

```python

%R require(dplyr)
%R data <- iris %>% group_by(Species) %>% summarise_all(funs(mean))

%R -o data
data
```

<img width="564" alt="スクリーンショット 2017-12-12 1.54.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/164610/76e299a5-f2e3-bd86-1642-a7c531c4adf7.png">


あとは、`%R -o`でPython側に渡したデータでplotなどをしていけば色々できそうな気配がしてきますね。

## まとめ

以上、簡単に一つのノートブック内にRとPythonを共存させる方法を紹介させていただきました。
基本的に`%load_ext`　`$R -i`　`%R -o`の3つを覚えておけば、あとは渡されるデータの型などに合わせて処理をおこなえば、だいたいのことはできると思います。