2010-07-26 59 views
4

我试图从python执行R脚本,理想地显示并保存结果。使用rpy2已经有点困难了,所以我想我会直接调用R。我有一种感觉,我需要使用诸如“os.system”或“subprocess.call”之类的东西,但我很难破译模块指南。问题在Python中运行程序(R)以执行操作(执行脚本)

这是R脚本“MantelScript”,它使用特定的统计测试来比较两个距离矩阵(distmatA1和distmatB1)。这在R中有效,尽管我还没有放入迭代位以读取和比较一堆文件(,我真的需要一些帮助,太btw了!):

library(ade4) 

M1<-read.table("C:\\pythonscripts\\distmatA1.csv", header = FALSE, sep = ",") 
M2<-read.table("C:\\pythonscripts\\distmatB1.csv", header = FALSE, sep = ",") 

mantel.rtest(dist(matrix(M1, 14, 14)), dist(matrix(M2, 14, 14)), nrepet = 999) 

这是我的python脚本的相关位,它通过一些先前制定的列表读取并抽出矩阵,以便通过此Mantel测试比较它们(它应该从identityA中拉出第一个矩阵,并将其依次与每个矩阵进行比较identityB,然后用identityB等的第二个矩阵重复)。我想保存这些文件,然后调用R程序进行比较:

# windownA and windownB are lists containing ascending sequences of integers 
# identityA and identityB are lists where each field is a distance matrix. 

z = 0 
v = 0 

import subprocess 
import os 

for i in windownA:        

    M1 = identityA[i]       

    z += 1 
    filename = "C:/pythonscripts/distmatA"+str(z)+".csv" 
    file = csv.writer(open(filename, 'w')) 
    file.writerow(M1) 


    for j in windownB:       

     M2 = identityB[j]      

     v += 1 
     filename2 = "C:/pythonscripts/distmatB"+str(v)+".csv" 
     file = csv.writer(open(filename2, 'w')) 
     file.writerow(M2) 

     ## result = os.system('R CMD BATCH C:/R/library/MantelScript.R') - maybe something like this?? 

     ## result = subprocess.call(['C:/R/library/MantelScript.txt']) - or maybe this?? 

     print result 
     print ' ' 

回答

2

坚持这一点。

process = subprocess.Popen(['R', 'CMD', 'BATCH', 'C:/R/library/MantelScript.R']) 
process.wait() 

当所述wait()函数返回.R文件完成的值。

请注意,您应该编写您的.R脚本来生成一个Python程序可以读取的文件。

with open('the_output_from_mantelscript', 'r') as result: 
    for line in result: 
     print(line) 

不要浪费很多时间来尝试连接管道。

投入时间获取基本的“Python衍生R”过程。

您可以稍后添加。

+0

感谢您的回复。我暂时选择在R中编写脚本,并且在用python保存.csv文件之后执行它,因为我有时间限制。该代码仍然存在一个问题,但是(作为“外行”)发现它更容易处理。 – user393200 2010-07-28 15:01:46

+0

@ vehicularlambslaughter.myopenid.c:“发现它更容易处理”这也是我的看法。一个程序写文件而另一个程序读文件的简单管道是最好的。用“子过程”欺骗太多通常不会有帮助。 – 2010-07-28 18:22:17

5

如果你的R脚本只有副作用,但是如果你想用Python进一步处理结果,你仍然会更好地使用rpy2。

import rpy2.robjects 
f = file("C:/R/library/MantelScript.R") 
code = ''.join(f.readlines()) 
result = rpy2.robjects.r(code) 
# assume that MantelScript creates a variable "X" in the R GlobalEnv workspace 
X = rpy2.rojects.globalenv['X'] 
+0

我认为rpy2会使事情运行更顺利,但我昨天决定坚持用更直接的方式在R中直接执行脚本 – user393200 2010-07-28 15:03:22

+0

@vehicularlambslaughter:这可能会限制不得不使用弃用包;你使用的是MSWindows,并且该OS上的rpy2是一个主要版本(类UNIX上的2.0.x和2.1.x)。如果你保持模块化的东西,你将总是能够很容易地切换回来(如果需要的话)(或者最近的rpy2最终到达MSWindows)。 – lgautier 2010-07-29 06:19:04

0

鉴于你想要做什么,一个纯的R解决方案可能是整洁:

file.pairs <- combn(dir(pattern="*.csv"), 2) # get every pair of csv files in the current dir 

的对是在2×N个矩阵列:

file.pairs[,1] 
[1] "distmatrix1.csv" "distmatrix2.csv" 

您可以运行通过使用apply(使用选项'2',意思是'act over columns')在这些列上的函数:

my.func <- function(v) paste(v[1], v[2], sep="::") 
apply(file.pairs, 2, my.func) 

在此示例中my.func只是将两个文件名粘合在一起;你可以用函数,它的Mantel检验,像(未经测试)替换此:

my.func <- function(v){ 
    M1<-read.table(v[1], header = FALSE, sep = ",") 
    M2<-read.table(v[2], header = FALSE, sep = ",") 
    mantel.rtest(dist(matrix(M1, 14, 14)), dist(matrix(M2, 14, 14)), nrepet = 999) 
} 
+0

啊谢谢,这将比我刚刚在R中发现的脚本更加整洁:http://stackoverflow.com/questions/3354115/writing-a-rtest-output-to-file-using-the-r-程序,通过写入表 我需要阅读组“A”和“B”的文件的每个组合 – user393200 2010-07-28 15:00:10

+0

不客气!我对'rpy2'的个人感觉是,它是专门用于* python和R *两种语言的专家的工具。如果你对这两种语言都不确定,那么rpy2会成为你问题的一个倍增因素。 – 2010-07-28 15:08:49

+0

尽管rpy2在定义上是一个专业工具(事实上R是一个专业工具),但它不应该需要R的专业知识(不幸的是,使用Python进行编程的知识将是不可避免的)。 rpy2的文档越来越多,如果您的体验符合您的个人感受,请报告它们(rpy2 bug跟踪器,rpy邮件列表等),以便让开发人员更好地了解它们。 – lgautier 2010-07-29 06:30:56

2

如果你有兴趣在一般的Python调用的R子。

#!/usr/bin/env python3 

from io import StringIO 
from subprocess import PIPE, Popen 

def rnorm(n): 
    rscript = Popen(["Rscript", "-"], stdin=PIPE, stdout=PIPE, stderr=PIPE) 
    with StringIO() as s: 
     s.write("x <- rnorm({})\n".format(n)) 
     s.write("cat(x, \"\\n\")\n") 
     return rscript.communicate(s.getvalue().encode()) 

if __name__ == '__main__': 
    output, errmsg = rnorm(5) 
    print("stdout:") 
    print(output.decode('utf-8').strip()) 
    print("stderr:") 
    print(errmsg.decode('utf-8').strip()) 

更好的通过RSCRIPT做到这一点。