Run an executable in R script - r

Is there a way to run an executable from R and capture its output?
As an example:
output <- run_exe("my.exe")

Yes, look at system() and its options. Hence
R> res <- system("echo 4/3 | bc -l", intern=TRUE)
R> res
[1] "1.33333333333333333333"
R>
would be one way to divide four by three in case you mistrust the R engine itself.

Related

How to output the result of a PowerShell cmdlet run in R(system2) as a dataframe

I'm trying to run some PS cmdlets in R with system2 but I cannot find a way of outputting the result into an R data frame.
Example:
PSCommand_ConnectToMSOL <- "Connect-MsolService"
PSCommand_GetAllLicensingPlans <- "Get-MsolAccountSku | ft SkuPartNumber, ActiveUnits, ConsumedUnits"
PS_output <- system2("powershell", args = PSCommand_ConnectToMSOL, PSCommand_GetAllLicensingPlans)
PS_output
The result in PowerShell is:
However in R studio I don't see a result:
How can I output the results to a data frame?
You have a typo/incorrect syntax in your code. Per the system2 documentation, the args argument takes in a character vector (i.e. character()):
Change:
PS_output <- system2("powershell", args = PSCommand_ConnectToMSOL, PSCommand_GetAllLicensingPlans)
to
PS_output <- system2("powershell", args = c(PSCommand_ConnectToMSOL, PSCommand_GetAllLicensingPlans))
With the original code you posted the PSCommand_GetAllLicensingPlans variable would be passed onto the stdout system2 argument which wouldn't make any sense..
Maybe try examining your code just a smidge more before looking for outside help next time!

bash argument containing R column info, from character to numeric

Trying to pass column coordinates from bash to an R script. For example:
Rscript script.R Input.table "29:37,40:48" "11:19" Output.file
I then have the script
#!/usr/bin/env Rscript
args <- commandArgs(trailingOnly = TRUE)
a <- read.table(args[1], header=T, row.names=1)
locg1 <- c(args[2])
locg2 <- c(args[3])
meangroup1 <- mean(a[,locg1])
meangroup2 <- mean(a[,locg2])
However when I run the script I get execution halted with "undefined columns selected" as an error.
I believe it's because the bash arguments are all interpreted as character and I am not sure how to convert a character like "29:37,40:48" into an actual numerical list.
I'm not expert in using Rscript from the command line to call R scripts, but given this simplified version:
Rscript script.R "29:37,40:48"
we can try using strsplit to separate the two times:
times <- strsplit(args[1], ",")[[1]]
locg1 <- times[1]
locg2 <- times[2]

Passing command line arguments to R CMD BATCH

I have been using R CMD BATCH my_script.R from a terminal to execute an R script. I am now at the point where I would like to pass an argument to the command, but am having some issues getting it working. If I do R CMD BATCH my_script.R blabla then blabla becomes the output file, rather than being interpreted as an argument available to the R script being executed.
I have tried Rscript my_script.R blabla which seems to pass on blabla correctly as an argument, but then I don't get the my_script.Rout output file that I get with R CMD BATCH (I want the .Rout file). While I could redirect the output of a call to Rscript to a file name of my choosing, I would not be getting the R input commands included in the file in the way R CMD BATCH does in the .Rout file.
So, ideally, I'm after a way to pass arguments to an R script being executed via the R CMD BATCH method, though would be happy with an approach using Rscript if there is a way to make it produce a comparable .Rout file.
My impression is that R CMD BATCH is a bit of a relict. In any case, the more recent Rscript executable (available on all platforms), together with commandArgs() makes processing command line arguments pretty easy.
As an example, here is a little script -- call it "myScript.R":
## myScript.R
args <- commandArgs(trailingOnly = TRUE)
rnorm(n=as.numeric(args[1]), mean=as.numeric(args[2]))
And here is what invoking it from the command line looks like
> Rscript myScript.R 5 100
[1] 98.46435 100.04626 99.44937 98.52910 100.78853
Edit:
Not that I'd recommend it, but ... using a combination of source() and sink(), you could get Rscript to produce an .Rout file like that produced by R CMD BATCH. One way would be to create a little R script -- call it RscriptEcho.R -- which you call directly with Rscript. It might look like this:
## RscriptEcho.R
args <- commandArgs(TRUE)
srcFile <- args[1]
outFile <- paste0(make.names(date()), ".Rout")
args <- args[-1]
sink(outFile, split = TRUE)
source(srcFile, echo = TRUE)
To execute your actual script, you would then do:
Rscript RscriptEcho.R myScript.R 5 100
[1] 98.46435 100.04626 99.44937 98.52910 100.78853
which will execute myScript.R with the supplied arguments and sink interleaved input, output, and messages to a uniquely named .Rout.
Edit2:
You can run Rscript verbosely and place the verbose output in a file.
Rscript --verbose myScript.R 5 100 > myScript.Rout
After trying the options described here, I found this post from Forester in r-bloggers . I think it is a clean option to consider.
I put his code here:
From command line
$ R CMD BATCH --no-save --no-restore '--args a=1 b=c(2,5,6)' test.R test.out &
Test.R
##First read in the arguments listed at the command line
args=(commandArgs(TRUE))
##args is now a list of character vectors
## First check to see if arguments are passed.
## Then cycle through each element of the list and evaluate the expressions.
if(length(args)==0){
print("No arguments supplied.")
##supply default values
a = 1
b = c(1,1,1)
}else{
for(i in 1:length(args)){
eval(parse(text=args[[i]]))
}
}
print(a*2)
print(b*3)
In test.out
> print(a*2)
[1] 2
> print(b*3)
[1] 6 15 18
Thanks to Forester!
You need to put arguments before my_script.R and use - on the arguments, e.g.
R CMD BATCH -blabla my_script.R
commandArgs() will receive -blabla as a character string in this case. See the help for details:
$ R CMD BATCH --help
Usage: R CMD BATCH [options] infile [outfile]
Run R non-interactively with input from infile and place output (stdout
and stderr) to another file. If not given, the name of the output file
is the one of the input file, with a possible '.R' extension stripped,
and '.Rout' appended.
Options:
-h, --help print short help message and exit
-v, --version print version info and exit
--no-timing do not report the timings
-- end processing of options
Further arguments starting with a '-' are considered as options as long
as '--' was not encountered, and are passed on to the R process, which
by default is started with '--restore --save --no-readline'.
See also help('BATCH') inside R.
In your R script, called test.R:
args <- commandArgs(trailingOnly = F)
myargument <- args[length(args)]
myargument <- sub("-","",myargument)
print(myargument)
q(save="no")
From the command line run:
R CMD BATCH -4 test.R
Your output file, test.Rout, will show that the argument 4 has been successfully passed to R:
cat test.Rout
> args <- commandArgs(trailingOnly = F)
> myargument <- args[length(args)]
> myargument <- sub("-","",myargument)
> print(myargument)
[1] "4"
> q(save="no")
> proc.time()
user system elapsed
0.222 0.022 0.236
I add an answer because I think a one line solution is always good!
Atop of your myRscript.R file, add the following line:
eval(parse(text=paste(commandArgs(trailingOnly = TRUE), collapse=";")))
Then submit your script with something like:
R CMD BATCH [options] '--args arguments you want to supply' myRscript.R &
For example:
R CMD BATCH --vanilla '--args N=1 l=list(a=2, b="test") name="aname"' myscript.R &
Then:
> ls()
[1] "N" "l" "name"
Here's another way to process command line args, using R CMD BATCH. My approach, which builds on an earlier answer here, lets you specify arguments at the command line and, in your R script, give some or all of them default values.
Here's an R file, which I name test.R:
defaults <- list(a=1, b=c(1,1,1)) ## default values of any arguments we might pass
## parse each command arg, loading it into global environment
for (arg in commandArgs(TRUE))
eval(parse(text=arg))
## if any variable named in defaults doesn't exist, then create it
## with value from defaults
for (nm in names(defaults))
assign(nm, mget(nm, ifnotfound=list(defaults[[nm]]))[[1]])
print(a)
print(b)
At the command line, if I type
R CMD BATCH --no-save --no-restore '--args a=2 b=c(2,5,6)' test.R
then within R we'll have a = 2 and b = c(2,5,6). But I could, say, omit b, and add in another argument c:
R CMD BATCH --no-save --no-restore '--args a=2 c="hello"' test.R
Then in R we'll have a = 2, b = c(1,1,1) (the default), and c = "hello".
Finally, for convenience we can wrap the R code in a function, as long as we're careful about the environment:
## defaults should be either NULL or a named list
parseCommandArgs <- function(defaults=NULL, envir=globalenv()) {
for (arg in commandArgs(TRUE))
eval(parse(text=arg), envir=envir)
for (nm in names(defaults))
assign(nm, mget(nm, ifnotfound=list(defaults[[nm]]), envir=envir)[[1]], pos=envir)
}
## example usage:
parseCommandArgs(list(a=1, b=c(1,1,1)))

R: is there a command for the end of a file that states whether any errors occurred?

Sometimes when I am running lots of long programs I think it would be nice if there was a statement or command I could add to the bottom of a file that would tell me whether R returned any error messages (or warning messages) while running a file.
I always scroll up through all of the code to visually check for error messages or warnings and keep thinking it would be nice if R simply told me at the bottom of the code whether any error messages or warnings occurred.
Can R do that? I suppose even if R can do that I would need a while to develop trust in the command line to catch all error messages or warning messages.
With SAS I used to use the find command and search the log window for the word ‘Error’ or ‘Warning’.
Thanks for any thoughts or advice about this.
Here is a very simple example of R code that returns 3 error messages.
x <- c(1,2,3,4)
y <- c(3,4)
z <- x / y
zz
a <- matrix(x, nrow=2, byrow=T)
b <- matrix(x, nrows=2, byrow=T)
z x a
z * a
I assume you are running from a GUI, where errors are not fatal. Here is a solution making use of options(error). The error handler is replaced by a function that increments a variable:
.error.count <- 0
old.error.fun <- getOption("error")
new.error.fun <- quote(.error.count <- .error.count + 1)
options(error = new.error.fun)
### your code here ###
x <- c(1,2,3,4)
y <- c(3,4)
z <- x / y
zz
a <- matrix(x, nrow=2, byrow=T)
b <- matrix(x, nrows=2, byrow=T)
z x a
z * a
######################
cat("ERROR COUNT:", .error.count, "\n")
options(error = old.error.fun)
rm(.error.count, old.error.fun, new.error.fun)
this is not a good example, because when i run it, it stops on the first error. however, the general question is probably better solved by the OS and the standard file descriptors. specifically, R will output its normal output to stdout, and its warnings and errors to stderr, and you can deal with those streams separately rather than seeing them together. for example, you can send stdout to a file and keep stderr in the terminal:
Rscript myfile.R 1>output.txt
I get this functionality primarily by using source() to run code; i.e., just dump your code into a file and then run:
source("yourscript.r")
in R, which returns:
Error in source("yourscript.r") : yourscript.r:7:3: unexpected symbol
6: b <- matrix(x, nrows=2, byrow=T)
7: z x
^
It doesn't return all the errors in one pass - syntax errors will stop the file from executing at all, unlike checkorbored's Rscript method that runs and then gives you the first error (see ?source for more details). But it might serve your purposes.
similar to #checkorboard
what I do is put the code in a text file, say "yourscript.r" and then run:
R CMD BATCH yourscript.r &
This will automatically create a file like yourscript.rout with the output of the program and you can easily grep to see if there was an error.

Difference between Rscript and littler

...besides the fact that Rscript is invoked with #!/usr/bin/env Rscript and littler with #!/usr/local/bin/r (on my system) in first line of script file. I've found certain differences in execution speed (seems like littler is a bit slower).
I've created two dummy scripts, ran each 1000 times and compared average execution time.
Here's the Rscript file:
#!/usr/bin/env Rscript
btime <- proc.time()
x <- rnorm(100)
print(x)
print(plot(x))
etime <- proc.time()
tm <- etime - btime
sink(file = "rscript.r.out", append = TRUE)
cat(paste(tm[1:3], collapse = ";"), "\n")
sink()
print(tm)
and here's the littler file:
#!/usr/local/bin/r
btime <- proc.time()
x <- rnorm(100)
print(x)
print(plot(x))
etime <- proc.time()
tm <- etime - btime
sink(file = "little.r.out", append = TRUE)
cat(paste(tm[1:3], collapse = ";"), "\n")
sink()
print(tm)
As you can see, they are almost identical (first line and sink file argument differ). Output is sinked to text file, hence imported in R with read.table. I've created bash script to execute each script 1000 times, then calculated averages.
Here's bash script:
for i in `seq 1000`
do
./$1
echo "####################"
echo "Iteration #$i"
echo "####################"
done
And the results are:
# littler script
> mean(lit)
user system elapsed
0.489327 0.035458 0.588647
> sapply(lit, median)
L1 L2 L3
0.490 0.036 0.609
# Rscript
> mean(rsc)
user system elapsed
0.219334 0.008042 0.274017
> sapply(rsc, median)
R1 R2 R3
0.220 0.007 0.258
Long story short: beside (obvious) execution-time difference, is there some other difference? More important question is: why should/shouldn't you prefer littler over Rscript (or vice versa)?
Couple quick comments:
The path /usr/local/bin/r is arbitrary, you can use /usr/bin/env r as well as we do in some examples. As I recall, it limits what other arguments you can give to r as it takes only one when invoked via env
I don't understand your benchmark, and why you'd do it that way. We do have timing comparisons in the sources, see tests/timing.sh and tests/timing2.sh. Maybe you want to split the test between startup and graph creation or whatever you are after.
Whenever we ran those tests, littler won. (It still won when I re-ran those right now.) Which made sense to us because if you look at the sources to Rscript.exe, it works different by setting up the environment and a command string before eventually calling execv(cmd, av). littler can start a little quicker.
The main price is portability. The way littler is built, it won't make it to Windows. Or at least not easily. OTOH we have RInside ported so if someone really wanted to...
Littler came first in September 2006 versus Rscript which came with R 2.5.0 in April 2007.
Rscript is now everywhere where R is. That is a big advantage.
Command-line options are a little more sensible for littler in my view.
Both work with CRAN packages getopt and optparse for option parsing.
So it's a personal preference. I co-wrote littler, learned a lot doing that (eg for RInside) and still find it useful -- so I use it dozens of times each day. It drives CRANberries. It drives cran2deb. Your mileage may, as hey say, vary.
Disclaimer: littler is one of my projects.
Postscriptum: I would have written the test as
I would have written this as
fun <- function { X <- rnorm(100); print(x); print(plot(x)) }
replicate(N, system.time( fun )["elapsed"])
or even
mean( replicate(N, system.time(fun)["elapsed"]), trim=0.05)
to get rid of the outliers. Moreover, you only essentially measure I/O (a print, and a plot) which both will get from the R library so I would expect little difference.

Resources