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

Posted

技术标签:

【中文标题】在 Python 中运行程序 (R) 以执行操作(执行脚本)的问题【英文标题】:issue running a program (R) in Python to perform an operation (execute a script) 【发布时间】: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 ' '

【问题讨论】:

【参考方案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 中找到的脚本更简洁:***.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 来完成。

【讨论】:

以上是关于在 Python 中运行程序 (R) 以执行操作(执行脚本)的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在交互式环境中执行Python程序

如何在交互式环境中执行Python程序

如何在交互式环境中执行Python程序

在 R 中运行的 Python 脚本导入错误 [关闭]

Python学习教程(Python学习路线):教你如何在交互式环境中执行Python程序

文件操作——python基础篇