2010-07-26 63 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做到這一點。