проблема запуска программы (R) на Python для выполнения операции (выполнить скрипт) - PullRequest
4 голосов
/ 27 июля 2010

Я пытаюсь выполнить R-скрипт из python, в идеале отображать и сохранять результаты. Использование rpy2 было сложной задачей, поэтому я подумал, что просто позвоню напрямую. У меня такое чувство, что мне нужно использовать что-то вроде "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, который читает некоторые ранее сформулированные списки и извлекает матрицы, чтобы сравнить их с помощью этого теста Мантеля (он должен извлечь первую матрицу из 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 ' '

Ответы [ 4 ]

5 голосов
/ 27 июля 2010

Если ваш 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']
2 голосов
/ 28 июля 2010

В случае, если вы заинтересованы в общем вызове подпроцесса 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.

2 голосов
/ 27 июля 2010

Придерживайтесь этого.

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 spawnns R".

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

0 голосов
/ 28 июля 2010

Учитывая то, что вы пытаетесь сделать, чистое решение 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 просто склеивает два имени файла; Вы можете заменить это функцией, выполняющей тест Мантеля, что-то вроде (не проверено):

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