【问题标题】:issue running a program (R) in Python to perform an operation (execute a script)在 Python 中运行程序 (R) 以执行操作(执行脚本)的问题
【发布时间】:2011-03-21 07:54:18
【问题描述】:

我想从 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 ' '

【问题讨论】:

    标签: python r subprocess os.system rpy2


    【解决方案1】:

    坚持下去。

    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 spawns R”流程正常工作。

    您可以稍后添加。

    【讨论】:

    • 感谢您的回复。考虑到我有时间限制,我暂时选择在 R 中编写一个脚本并在使用 python 保存 .csv 文件后执行它。该代码仍有一个问题,但(作为“外行”)发现它更易于使用。
    • @vehicularlambslaughter.myopenid.c:“发现它更容易使用”这也是我的观点。一个程序写入文件而另一个程序读取文件的简单管道是最好的。用subprocess 玩弄太多通常无济于事。
    【解决方案2】:

    如果你的 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']
    

    【讨论】:

    • 我认为 rpy2 会让事情运行得更顺畅,但我昨天决定坚持使用更麻烦但直接在 R 中执行脚本的直接方法
    • @vehicularlambslaughter :这可能会限制不得不使用已弃用的软件包的挫败感;您使用的是 MSWindows,并且该操作系统上的 rpy2 是一个主要版本(2.0.x 与 UNIX 上的 2.1.x 类似)。如果您保持模块化,您将始终能够在需要时轻松切换回来(或者更新的 rpy2 终于出现在 MSWindows 上)。
    【解决方案3】:

    鉴于您正在尝试做的事情,纯 R 解决方案可能会更简洁:

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

    这些对是 2xN 矩阵中的列:

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

    您可以使用 apply 对这些列运行函数(使用选项 '2',意思是“对列进行操作”):

    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)
    }
    

    【讨论】:

    • 啊,谢谢,这将比我刚刚在 R 中找到的脚本更简洁:stackoverflow.com/questions/3354115/… 我需要读取来自“A”和“B”组的文件的每个组合跨度>
    • 不客气!我对rpy2 的个人感觉是,它是both python 和R 方面的专家的专业工具。如果您对这两种语言中的任何一种都有点不确定,那么 rpy2 可以作为您的问题的乘数。
    • 虽然 rpy2 被定义为专业工具(正如 R 实际上是专业工具一样),但它不需要 R 专业知识(不幸的是,使用 Python 编程的知识是不可避免的)。 rpy2 的文档越来越多,如果您有符合您个人感受的经验,请报告它们(rpy2 错误跟踪器、rpy 邮件列表等),以便开发人员更好地了解它们。
    • @lgautier: rpy2 非常棒,我当然不想在邮件列表中提交任何错误报告或抱怨。但在发挥这两种工具的优势时,它处于最佳状态,例如从网络上抓取数据,然后从中生成统计图形。这是基本文件操作的重量级解决方案(如this question);我认为初学者 R 用户会发现学习纯粹在 R 中完成基本任务既简单又具有普遍价值。
    【解决方案4】:

    如果您有兴趣从 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 来完成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-14
      • 2013-12-10
      相关资源
      最近更新 更多