web-dev-qa-db-fra.com

Exécuter un script R à partir de python

J'ai cherché cette question et ai trouvé quelques réponses à ce sujet, mais aucune d'entre elles ne semble fonctionner. C'est le script que j'utilise en python pour exécuter mon script R.

import subprocess
retcode = subprocess.call("/usr/bin/Rscript --Vanilla -e 'source(\"/pathto/MyrScript.r\")'", Shell=True)

et j'obtiens cette erreur:

Error in read.table(file = file, header = header, sep = sep, quote = quote,  : 
  no lines available in input
Calls: source ... withVisible -> eval -> eval -> read.csv -> read.table
Execution halted

et voici le contenu de mon script R (assez simple!)

data = read.csv('features.csv')
data1 = read.csv("BagofWords.csv")
merged = merge(data,data1)
write.table(merged, "merged.csv",quote=FALSE,sep=",",row.names=FALSE)
for (i in 1:length(merged$fileName))
{
        fileConn<-file(paste("output/",toString(merged$fileName[i]),".txt",sep=""))
        writeLines((toString(merged$BagofWord[i])),fileConn)
        close(fileConn)
}

Le script r fonctionne bien lorsque j'utilise source('MyrScript.r') dans la ligne de commande r. De plus, lorsque j'essaie d'utiliser la commande exacte que je passe à la fonction subprocess.call (c'est-à-dire, /usr/bin/Rscript --Vanilla -e 'source("/pathto/MyrScript.r")') dans ma ligne de commande, cela fonctionne, je ne comprends pas vraiment le problème.

30
Ehsan

Je ne ferais pas trop confiance au source au sein de l'appel Rscript, car vous ne comprendrez peut-être pas complètement où exécutez-vous vos différentes sessions imbriquéesR. Le processus peut échouer à cause de choses simples telles que votre répertoire de travail n'est pas celui que vous pensez.

Rscript vous permet d'exécuter directement un script (voir man Rscript si vous utilisez Linux).

Ensuite, vous pouvez faire directement: 

subprocess.call ("/usr/bin/Rscript --Vanilla /pathto/MyrScript.r", Shell=True)

ou mieux d'analyser la commande Rscript et ses paramètres sous forme de liste

subprocess.call (["/usr/bin/Rscript", "--Vanilla", "/pathto/MyrScript.r"])

En outre, pour simplifier les choses, vous pouvez créer un fichier exécutable R. Pour cela, il vous suffit d'ajouter ceci à la première ligne du script:

#! /usr/bin/Rscript

et lui donner des droits d'exécution. Voir ici pour detalis. 

Ensuite, vous pouvez simplement faire votre appel python comme s'il s'agissait de n'importe quelle commande ou script de Shell:

subprocess.call ("/pathto/MyrScript.r")
34
dmontaner

Je pense que RPy2 vaut la peine d’être examiné. Voici une présentation intéressante sur R-bloggers.com pour vous aider à démarrer:

http://www.r-bloggers.com/accessing-r-from-python-using-rpy2/

Pour l’essentiel, il vous permet d’avoir accès aux bibliothèques R avec des objets R qui fournissent une interface de haut niveau et de bas niveau.

Voici la documentation sur la version la plus récente: https://rpy2.readthedocs.io

J'aime pointer les utilisateurs Python vers Anaconda, et si vous utilisez le gestionnaire de paquets, conda, pour installer rpy2, vous aurez également la garantie d'installer R.

$ conda install rpy2

Et voici un vignet basé sur l'introduction des documents:

>>> from rpy2 import robjects
>>> pi = robjects.r['pi']
>>> pi
R object with classes: ('numeric',) mapped to:
<FloatVector - Python:0x7fde1c00a088 / R:0x562b8fbbe118>
[3.141593]

>>> from rpy2.robjects.packages import importr
>>> base = importr('base')
>>> utils = importr('utils')

>>> import rpy2.robjects.packages as rpackages
>>> utils = rpackages.importr('utils')
>>> packnames = ('ggplot2', 'hexbin')
>>> from rpy2.robjects.vectors import StrVector
>>> names_to_install = [x for x in packnames if not rpackages.isinstalled(x)]
>>> if len(names_to_install) > 0:
...     utils.install_packages(StrVector(names_to_install))

Et exécuter un extrait de code R:

>>> robjects.r('''
...         # create a function `f`
...         f <- function(r, verbose=FALSE) {
...             if (verbose) {
...                 cat("I am calling f().\n")
...             }
...             2 * pi * r
...         }
...         # call the function `f` with argument value 3
...         f(3)
...         ''')
R object with classes: ('numeric',) mapped to:
<FloatVector - Python:0x7fde1be0d8c8 / R:0x562b91196b18>
[18.849556]

Et une petite démo graphique autonome:

from rpy2.robjects.packages import importr
graphics = importr('graphics')
grdevices = importr('grDevices')
base = importr('base')
stats = importr('stats')

import array

x = array.array('i', range(10))
y = stats.rnorm(10)

grdevices.X11()

graphics.par(mfrow = array.array('i', [2,2]))
graphics.plot(x, y, ylab = "foo/bar", col = "red")

kwargs = {'ylab':"foo/bar", 'type':"b", 'col':"blue", 'log':"x"}
graphics.plot(x, y, **kwargs)


m = base.matrix(stats.rnorm(100), ncol=5)
pca = stats.princomp(m)
graphics.plot(pca, main="Eigen values")
stats.biplot(pca, main="biplot")
8
Aaron Hall

Essayez d'ajouter une ligne au début de votre script R qui dit:

setwd("path-to-working-directory")

Sauf que, remplacez le chemin par le chemin du dossier contenant les fichiers features.csv et BagofWords.csv

Je pense que le problème que vous rencontrez est dû au fait que lorsque vous exécutez ce script à partir de R, votre répertoire de travail est déjà le bon chemin, mais lorsque vous exécutez le script à partir de python, il utilise par défaut un répertoire de travail quelque part ). 

En ajoutant la ligne supplémentaire au début de votre script R, vous définissez explicitement le répertoire de travail et le code à lire dans ces fichiers fonctionnera. Vous pouvez également remplacer les noms de fichier dans read.csv() par les chemins d'accès complets à ces fichiers. 

@dmontaner a suggéré cette possibilité dans sa réponse:

Le processus peut échouer à cause de choses simples telles que votre répertoire de travail n'est pas celui que vous pensez.

1
enpitsu

Si vous souhaitez simplement exécuter un script, vous pouvez utiliser system("Shell command") de la sys lib disponible par import sys. Si vous avez une sortie utile, vous pouvez imprimer le résultat par " > outputfilename" à la fin de votre commande Shell.

Par exemple:

import sys

system("ls -al > output.txt")
0
Mips42