67

I searched for this question and found some answers on this, but none of them seem to work. This is the script that I'm using in python to run my R script.

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

and I get this error:

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

and here is the content of my R script (pretty 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)
}

The r script is working fine, when I use source('MyrScript.r') in r commandline. Moreover, when I try to use the exact command which I pass to the subprocess.call function (i.e., /usr/bin/Rscript --vanilla -e 'source("/pathto/MyrScript.r")') in my commandline it works find, I don't really get what's the problem.

mdml
  • 22,442
  • 8
  • 58
  • 66
Ehsan
  • 4,334
  • 7
  • 39
  • 59

6 Answers6

79

I would not trust too much the source within the Rscript call as you may not completely understand where are you running your different nested R sessions. The process may fail because of simple things such as your working directory not being the one you think.

Rscript lets you directly run an script (see man Rscript if you are using Linux).

Then you can do directly:

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

or better parsing the Rscript command and its parameters as a list

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

Also, to make things easier you could create an R executable file. For this you just need to add this in the first line of the script:

#! /usr/bin/Rscript

and give it execution rights. See here for detalis.

Then you can just do your python call as if it was any other shell command or script:

subprocess.call ("/pathto/MyrScript.r")
dmontaner
  • 2,076
  • 1
  • 14
  • 17
  • 1
    subprocess.call() didn't work in my case, but subprocess.Popen() works for me. Here is the example: process = subprocess.Popen(["R --vanilla --args %s %d %.2f < /path/to/your/rscript/transformMatrixToSparseMatrix.R" % ("sparse", 11, 0.98) ], shell=True) process.wait() – Good Will Sep 15 '16 at 11:24
  • All this worked the same for me: ```subprocess.call (['Rscript', '--vanilla', 'MyrScript.r']) subprocess.Popen(['Rscript', '--vanilla', 'MyrScript.r']) subprocess.call ('Rscript --vanilla MyrScript.r', shell=True) subprocess.Popen('Rscript --vanilla MyrScript.r', shell=True)``` If you do not break your parameters into a list is when you need to use `shell+True` I am not sure about parsing the arguments into Rscript using `<` – dmontaner Sep 16 '16 at 16:37
32

I think RPy2 is worth looking into, here is a cool presentation on R-bloggers.com to get you started:

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

Essentially, it allows you to have access to R libraries with R objects that provides both a high level and low level interface.

Here are the docs on the most recent version: https://rpy2.github.io/doc/latest/html/

I like to point Python users to Anaconda, and if you use the package manager, conda, to install rpy2, it will also ensure you install R.

$ conda install rpy2

And here's a vignet based on the documents' introduction:

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

And running an R snippet:

>>> 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]

And a small self-contained graphics demo:

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")
krassowski
  • 13,598
  • 4
  • 60
  • 92
Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
4

The following code should work out:

import rpy2.robjects as robjects
robjects.r.source("/pathto/MyrScript.r", encoding="utf-8")
ah bon
  • 9,293
  • 12
  • 65
  • 148
1

I would not suggest using a system call to there are many differences between python and R especially when passing around data.

There are many standard libraries to call R from Python to choose from see this answer

Community
  • 1
  • 1
pyCthon
  • 11,746
  • 20
  • 73
  • 135
  • Hi, here, I just need to run a simple script, so I don't want to stuck with setting up rpy2 or other libraries. – Ehsan Nov 10 '13 at 20:49
  • @Ehsan its fairly simple to setup and you will avoid reinventing the wheel. Are you on windows, mac or linux? – pyCthon Nov 10 '13 at 21:44
  • @Ehsan and another suggestion if all your doing is loading a csv file with R why not just rewrite the R code into python? – pyCthon Nov 10 '13 at 21:50
  • I'm using linux, it's not just loading a csv file, but I will take a loot at rpy2 and see how is it:) – Ehsan Nov 10 '13 at 23:05
  • yeah if your on ubuntu its as simple as `sudo apt-get install python-rpy2` – pyCthon Nov 10 '13 at 23:14
1

Try adding a line to the beginning of your R script that says:

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

Except, replace the path with the path to the folder containing the files features.csv and BagofWords.csv.

I think the problem you are having is because when you run this script from R your working directory is already the correct path, but when you run the script from python, it defaults to a working directory somewhere else (likely the top of the user directory).

By adding the extra line at the beginning of your R script, you are explicitly setting the working directory and the code to read in these files will work. Alternatively, you could replace the filenames in read.csv() with the full filepaths of these files.

@dmontaner suggested this possibility in his answer:

The process may fail because of simple things such as your working directory not being the one you think.

enpitsu
  • 636
  • 3
  • 6
0

If you just want run a script then you can use system("shell command") of the sys lib available by import sys. If you have an usefull output you can print the result by " > outputfilename" at the end of your shell command.

For example:

import sys

system("ls -al > output.txt")
Mips42
  • 56
  • 3
  • 1
    I didn't know this existed. Is it older/obsolete? Can it save the output as a string? – Tom Jul 01 '16 at 21:46
  • I don't know if it's obsolete but yes you can have the output. With this one you call a shell command so if you change the output target with > you can get results back with the output file. – Mips42 Jul 03 '16 at 19:37