在 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) 以执行操作(执行脚本)的问题的主要内容,如果未能解决你的问题,请参考以下文章