2010-07-26 2 views
4

Я связываюсь с тем, чтобы выполнить R-скрипт из python, идеально отображая и сохраняя результаты. Использование rpy2 было немного трудным, поэтому я подумал, что просто позвоню R напрямую. У меня такое ощущение, что мне нужно будет использовать что-то вроде «os.system» или «subprocess.call», но мне сложно расшифровать руководства по модулям.Запуск программы (R) в Python для выполнения операции (выполнить скрипт)

Вот сценарий R «MantelScript», который использует специальный тест stat для сравнения двух матриц расстояния за раз (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, который читает некоторые ранее сформулированные списки и вытягивает матрицы, чтобы сравнить их с помощью этого теста Мантела (он должен вытащить первую матрицу из идентификатора А и последовательно сравнить ее с каждой матрицей в identityB, затем повторите со второй матрицей из идентификатора B и т. д.). Я хочу сохранить эти файлы, а затем вызвать программу 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 spawns R».

Вы можете добавить к этому позже.

+0

благодарит за ответ. Я на данный момент решил написать скрипт в R и просто выполнить его после сохранения файлов .csv с помощью python, учитывая, что у меня было ограничение по времени. по-прежнему остается одна проблема с этим кодом, но (как «непрофессионал») было легче работать. – user393200

+0

@ vehicleularlambslaughter.myopenid.c: «С ним легче работать». Это мое мнение. Лучше всего использовать простые конвейеры, где одна программа записывает файл, а другая программа читает файл. Не слишком часто обманывать себя «подпроцессом». –

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

+0

@vehicularlambslaughter: это может ограничить разочарование в работе с устаревшим пакет; вы с MSWindows, а rpy2 - это одна из основных версий (2.0.x против 2.1.x на UNIX-подобном). Если вы храните вещи в модуле, вы всегда сможете легко переключиться обратно, если возникнет такая необходимость (или, наконец, более поздний rpy2 подходит для MSWindows). – lgautier

0

Учитывая то, что вы пытаетесь сделать, чистый 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" 

Вы можете запустить функцию с использованием применения (с опцией «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) 
} 
+0

ah спасибо, что это было бы намного опрятно, чем сценарий, который я только что написал в R, здесь: http://stackoverflow.com/questions/3354115/writing-a-rtest-output-to-file-using-the-r- program-ex-via-write-table Мне нужно читать в каждой комбинации файлов из групп «A» и «B» – user393200

+0

Добро пожаловать! Мое личное чувство на rpy2 состоит в том, что это инструмент специалиста для людей, которые являются экспертами в * обоих * python и R. Если вы немного сомневаетесь в любом из этих двух языков, тогда rpy2 действует как множитель ваших проблем. –

+0

Несмотря на то, что rpy2 по определению является специализированным инструментом (так как R - это инструмент специалиста), он не должен требовать экспертизы в R (знание программирования с Python будет неизбежно, к сожалению). Существует растущая документация для rpy2, и если у вас есть опыт, который соответствует вашему личному чувству, пожалуйста, сообщите о них (rpy2 bug tracker, rpy listing list и т. Д.), Поэтому они более известны разработчикам. – lgautier

2

В случае, если вы заинтересованы, в общем, вызывая в R подпроцесс из Python.

#!/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.