在Python中运行程序(R)以执行操作(执行脚本)的问题

4 投票
4 回答
3980 浏览
提问于 2025-04-16 01:52

我想从Python中执行一个R脚本,最好能显示和保存结果。使用rpy2让我有点头疼,所以我想直接调用R。我觉得我可能需要用到“os.system”或者“subprocess.call”,但是我在理解这些模块的使用说明时遇到了困难。

这是我的R脚本“MantelScript”,它使用一种特定的统计测试来比较两个距离矩阵(distmatA1和distmatB1)。这个在R中可以正常工作,不过我还没有加入循环的部分,以便逐个读取和比较一堆文件(顺便说一下,我真的需要一些帮助!):

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 ' '

4 个回答

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来实现这个功能。

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”的过程。

之后你可以再进行扩展。

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']

撰写回答