Rで分析したデータを、Pythonから分析したい (パッケージがPythonにしかない、Pythonのコード資産を活用したい、など) 場合のメモ。
自分のケース
Rの{caret}で機械学習にかけたデータを、Tensorflow/kerasを使ったニューラルネットワークにかけたい。
RでもTensorflow/kerasは使えるが、Pythonに比べると使いづらい。
分析用のデータは一旦csvに吐き出した後、R内でデータ型など加工しており、RDataに保存している。
RDataは2種類あり、説明変数のデータと、複数の目的変数が格納されているデータ。
目的変数の番号を指定して、説明変数+欲しい目的変数を取得したい。
使うもの
- データを保存しているRData
- pyper
自分が書いたコード
def readR(i):
r = pyper.R(use_numpy='True', use_pandas='True')
r("load('data/train.RData')")
r("train <- as.data.frame(train[,-1])") # 1列目はIDなので除外
r.assign(obj="i", val=i)
r("load('data/score.RData')")
r("target <- score[,i+1]") # 1列目はIDなので除外
r("name <- colnames(score[,-1])")
r("name <- gsub(':', '', name)")
r("name <- name[i]")
# pyperからpandasへ引き渡し
train = pd.DataFrame(r.get('train'))
score = pd.DataFrame(r.get('target'))
name = str(i).zfill(2) + "_" + r.get('name')
return train, score, name
trainが説明変数のデータ、scoreが目的変数のデータ (今考えると名前が変だ)。
3つめの返り値のnameは、目的変数の名前がカラムに書いてあるので、それを使っている。
nameを取得するのは、出力ファイルのディレクトリ名にするため。
汎用性を考えると、
簡単な説明
Pythonのpyperパッケージを使う。
Rのdata.frame型を引き取る際に、pandasのpd.DataFrameとして受け取るので、インスタンス作成時のオプションのuse_pandas='True'
は必須。
use_numpy='True'
はしなくても動くかもしれないが、別にしないメリットもあまりないので。
pyperの中は基本的にRのコマンドを書いていき、最後にr.get()でRのオブジェクトをPythonに引き渡すだけ。特に難しいことはないはず。
やってみた感想
思ったよりもメモリを食う。r.get()でRからPythonにオブジェクトを引き渡す時に、恐らくオブジェクトをまるごとコピーするのだが、そのせいでRで読んでた時の2倍+αのメモリを食う (+αどころか、元の3倍くらい食ってる気が……)。
巨大なデータのやり取りにpyperを使うのは避けた方が良さそう。
あと、scoreの方のデータフレームは、1列ずつ読み込んだが、全部一気に読み込もうとするとエラーで上手く行かなかった。
理由はよくわからないが、今思うとメモリが溢れていたのかもしれない……