RigelのR言語メモであーる(R言語だけとは言っていない)

RigelのR言語メモであーる(主にpython)

興味あることや趣味、やったことについて書くよ

RからPythonスクリプトを実行する

私はRをメインで使い、サブでPythonを使います。
そんな私は、「基本はRで処理して、この処理だけPythonでやりたい!」と思うときがたまにあります。
そういったとき、RからPythonスクリプトを実行すれば解決します。
だけど、コマンドライン引数や返り値の書き方が覚えられない。
毎回調べるのも面倒なので本記事にメモしておきます。

とりあえずPythonスクリプトをRから実行する

まずは、コマンドライン引数や返り値は考えない。
とりあえずPythonスクリプトをRから実行する。
以下のPythonコードを"hello.py"で適当に保存。

print('Hello World')

次に"hello.py"をRから実行する。
Rで"hello.py"があるディレクトリに行って、以下のRコードを実行する。

system("python hello.py")

すると、

> system("python hello.py")
Hello World

と表示されるはずです。簡単ですね!

Pythonスクリプトの返り値を受け取る

次は、RからPythonスクリプトを実行し、その返り値をRで受け取ります。
まずは以下のRコードを実行してみます。

ret=system("python hello.py")
ret

すると、

> ret=system("python hello.py")
Hello World
> ret
[1] 0

こうなって返り値として受け取れない。
返り値として受け取るには、Rのsystem関数の引数でintern=Tとするだけです。つまり、

ret=system("python hello.py",intern=T)
ret

とするだけです。実行すると、

> ret=system("python hello.py",intern=T)
> ret
[1] "Hello World"

と表示されます。無事に返り値として受け取ることができました!
ちなみに複数の返り値を受け取りたい場合は、pythonで複数回printするだけです。
"hello.py"を以下に変更します。

print('Hello World1')
print('Hello World2')
print('Hello World3')

そして、Rから実行してみます。

> ret=system("python hello.py",intern=T)
> ret
[1] "Hello World1" "Hello World2" "Hello World3"

いい感じです!

Pythonスクリプトコマンドライン引数を渡す

最後にPythonスクリプトコマンドライン引数を渡します。
"hello.py"を以下に変更します。

import sys
for i in range(len(sys.argv)):
    print(sys.argv[i])

そして、Rから

ret=system("python hello.py a b c",intern=T)
ret

と実行してみます。

> ret=system("python hello.py a b c",intern=T)
> ret
[1] "hello.py" "a"        "b"        "c" 

このように表示されたら成功です!
注意点としては、コマンドライン引数の1番目(Pythonでいう0番目)には自動でファイル名が入ることです。
そこだけ気をつけておきましょう。

まとめ

RからPythonスクリプトコマンドライン引数を渡して実行し、その結果を返り値として受け取る方法について記載しました。
もちろんある程度大きなデータのやりとりをする場合は、csvなどのファイルを経由したほうが良いと思われます。

補足

pyenvでpythonを管理していて、特定のバージョンで実行したいときは、以下のRコードをはじめに実行すれば良いです。

Sys.setenv(PATH=paste("/Users/KYO/.pyenv/versions/anaconda3-4.1.1/bin", Sys.getenv("PATH"),sep=":"))

(anaconda3-4.1.1で実行したい場合)