2019年1月14日月曜日

PythonでRのスクリプトを実行する

Raspberry Piに最新のR(3.5.2)をインストールするでRaspberry PiにRをインストールしたので、PythonからRを使ってみる。

PythonからRを使う方法としてはPypeRなどがあるらしいが、Rで検定を実行してその結果を表示するだけなら、Pythonのsubprocessモジュールでも十分。Pythonのsubprocessでコマンドを実行するのようにPythonからコマンドを実行できるので、RscriptをPythonから実行する。


環境


Raspberry PiとRaspbian Stretch with Desktop。



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


Rスクリプトをコマンドラインで実行するにはRscriptコマンドを使う。このコマンドは引数を受け取れるので、PythonでRスクリプトファイルを作成して、引数を含めてsubprocessモジュールで実行する。

以下のコードでは、平均が異なる正規分布に従う値を10ずつ生成してt検定を行うRスクリプトファイルを作成し、Rscriptで実行した結果を表示する。

※Rスクリプトがエラーのときにメッセージを出力するようにコード変更(2019.2.11)

import os
import sys
import subprocess
import textwrap
import random
def create_rscript(rscript_path):
"""Rスクリプトファイルの作成
"""
r_script = textwrap.dedent("""
# コマンドラインの引数取得
args1 <- commandArgs(trailingOnly = TRUE)[0:10]
args2 <- commandArgs(trailingOnly = TRUE)[11:20]
g1 <- as.numeric(args1)
g2 <- as.numeric(args2)
cat('g1=\n')
g1
summary(g1)
cat('g2=\n')
g2
summary(g2)
# t検定の結果出力
t.test(g1, g2, var.equal=TRUE)
""").strip()
with open(rscript_path,'w') as f:
f.write(r_script)
def main():
# Rスクリプトファイル名
rscript_path = 'r_script.R'
if not os.path.exists(rscript_path):
create_rscript(rscript_path)
else:
print('{}と同名ファイルが存在します。'.format(rscript_path))
sys.exit()
# 平均が異なる正規分布に従う値を10ずつ生成
# 値は文字列に変換しておく
g1 = [str(random.normalvariate(0, 1)) for i in range(10)]
g2 = [str(random.normalvariate(2, 1)) for i in range(10)]
# --vanilla はRscript実行時に余計なオブジェクト等を読み込まないためのオプション
cmd = ['Rscript', '--vanilla', rscript_path] + g1 + g2
try:
# check_outputでRスクリプトの実行結果を取得
# 結果はバイト列だが、universal_newlines=Trueとするとエンコードされる
res = subprocess.check_output(cmd, stderr=subprocess.STDOUT, universal_newlines=True)
except subprocess.CalledProcessError as e:
print(e.output)
else:
print(res)
os.remove(rscript_path)
if __name__ == '__main__':
main()
view raw runr.py hosted with ❤ by GitHub
結果は以下の通り。




0 件のコメント:

コメントを投稿