Currently I have an R Script that takes 8 parameters that are hard-coded as the first 8 lines of my script.
I've made a Batch file to try and manually change the parameters on the fly, but it doesn't seem to be working the way I want it to.
Batch that currently runs the script (But doesnt actually change the parameters)
echo off
ECHO PRESS ENTER AT ANY INPUT TO ACCEPT the DEFAULT VALUE.
:: Setting of Variables
#Set /P RScript=Set path to R:_
#Set /P RProgram=Set path to RScript:_
#Set /P RStartDir=Set Start Directory:_
#Set /P Begin=Begin on which Loan?:_
#Set /P End=End on which Loan?:_
#Set /P OutputDir=Set Output Directory:_
#Set /P Deal=Set Deal input file (.txt):_
#Set /P OutputFile=Name Deal Output File:_
#Set /P AsOfDate=As of Date?:_
#Set /P ThirtyYrSpread=Thirty Year Mortgage Spread?:_
:: If Blank (enter), set variables/paths to Defaults (Listed Below)
if "%RScript%"=="" Set RScript=c:\program files\r\r-
3.4.3\bin\x64\rscript.exe
if "%RProgram%"=="" Set RProgram=C:\MortgageMatt\Cirt2014-
1\0.Mortgage Model.R
if "%RStartDir%"=="" Set RStartDir=C:\MortgageMatt\Cirt2014-1
if "%Begin%"=="" Set Begin=1
if "%End%"=="" Set End=2
if "%OutputDir%"=="" Set OutputDir=C:\MortgageMatt\Cirt2014-1
if "%Deal%"=="" Set Deal=Cirt 2014-1 Loan Level.txt
if "%OutputFile%"=="" Set OutputFile=Cirt 2014-1d
if "%AsOfDate%"=="" Set AsOfDate=62017
if "%ThirtyYrSpread%" == "" Set ThirtyYrSpread=135
echo "%RScript% %RProgram% %RStartDir% %Begin% %End% %OutputDir% %Deal%
%OutputFile% %AsOfDate% %ThirtyYrSpread%"
ECHO PLEASE CHECK IF THESE VALUES ARE CORRECT
pause
:: Command Prompt, /c Carries out command specified by string and then
terminates
cmd /c ""%RScript%" "%RProgram%" "%RStartDir%" "%Begin%" "%End%"
"%OutputDir%" "%Deal%" "%OutputFile%" "%AsOfDate%" "%ThirtyYrSpread%""
So because the parameters were actually hard coded into the R Script, this is what I've added to try to accommodate. Does this look okay? I think this is where I'm running into errors.
Added to R Script
args <- commandArgs(trailingOnly = TRUE)
if (length(args) == 0) {
if (!exists("dataDir")) { stop("variables dataDir not found") }
# Set dataDir variable when Running inside a R Session
args <- c(getwd(), 1, 2, ".", "Cirt 2014-1 Loan Level.txt", "Cirt 2014-
1", "62017", 175)
}
print(args)
# Input Values
Input.Directory <- paste(args[1]) ## getwd() , "/", "inputs", sep = "")
Begin.Sim <- args[2]
End.Sim <- args[3]
Output.Directory <- paste(args[1],"\\",args[4],sep = "") ##, "/", "outputs",
sep = "")
Pool.ID.File <- args[5] #"Cirt 2014-1 Loan Level.txt"
Pool.ID <- args[6] #"Cirt 2014-1"
asofdate <- args[7] #"62017"
Thirty.Yr.Mort.Spread <- args[8] # 175
When I try to run it in cmd using the .bat.. I get an error that says cannot change working directory. Anyone have any suggestions?
I sort-of understand where the error is but I'm struggling to fix it.
The path to my file with everything in it is
C:\MortgageMatt\Cirt2014-1
Edit:
I've also heard of something called R CMD Batch... should I look into that? I'm finding that it's an older technique.
What my code looked like before the Args/IF
# Input Values
Input.Directory <- "C:/Mortgage/Cirt 2014 - 1"
Output.Directory <- "C:/Mortgage/Cirt 2014 - 1"
Pool.ID.File <- "Cirt 2014-1 Loan Level.txt"
Pool.ID <- "Cirt 2014-1 NEW"
start<- 1
sims <- 2 # Number of Simulations
asofdate <- "62017"
Thirty.Yr.Mort.Spread <- 175
You can do all of this in R using one of these packages to parse command-line options:
docopt (my favourite)
optparse
argparse
getopt
or doing it manually -- not recommended.
You also do not want the older R CMD BATCH -- use Rscript (or littler, but littler does not work on Windows).
Code Example
#!/usr/bin/Rscript
suppressMessages(library(docopt))
doc <- "Usage: foo.R [-h] [-x] [--src REPODIR] [--out OUTDIR] [FILES...]
-s --src REPODIR source root directory [default: ~/git]
-o --out OUTDIR output directory [default: /tmp]
-h --help show this help text"
opt <- docopt(doc) # docopt parsing
print(opt)
Use with -h
You get a nice message, automatically, with not formatting need:
edd#rob:/tmp$ Rscript so50256138.R -h
Usage: foo.R [-h] [-x] [--src REPODIR] [--out OUTDIR] [FILES...]
-s --src REPODIR source root directory [default: ~/git]
-o --out OUTDIR output directory [default: /tmp]
-h --help show this help text
edd#rob:/tmp$
Use with argument
Note how one default argument is used, and the other from the command-line:
edd#rob:/tmp$ Rscript so50256138.R -s A
List of 9
$ --src : chr "A"
$ --out : chr "/tmp"
$ --help: logi FALSE
$ -x : logi FALSE
$ FILES : list()
$ src : chr "A"
$ out : chr "/tmp"
$ help : logi FALSE
$ x : logi FALSE
NULL
You can access them in opt by name or by option flag.
The docopt site has more; this is actually a portable specification and the CRAN package implements it for R.
Related
For some reason, the optparse usage in this script breaks:
test.R:
#!/usr/bin/env Rscript
library("optparse")
option_list <- list(
make_option(c("-n", "--name"), type="character", default=FALSE,
dest="report_name", help="A different name to use for the file"),
make_option(c("-h", "--height"), type="numeric", default=12,
dest = "plot_height", help="Height for plot [default %default]",
metavar="plot_height"),
make_option(c("-w", "--width"), type="numeric", default=10,
dest = "plot_width", help="Width for plot [default %default]",
metavar="plot_width")
)
opt <- parse_args(OptionParser(option_list=option_list), positional_arguments = TRUE)
print(opt)
report_name <- opt$options$report_name
plot_height <- opt$options$plot_height
plot_width <- opt$options$plot_width
input_dir <- opt$args[1] # input directory
I get this error:
$ ./test.R --name "report1" --height 42 --width 12 foo
Error in getopt(spec = spec, opt = args) :
redundant short names for flags (column 2).
Calls: parse_args -> getopt
Execution halted
However, if I remove the "-h" from this line:
make_option(c("--height"), type="numeric", default=12,
dest = "plot_height", help="Height for plot [default %default]"
It seems to work fine;
$ ./test.R --name "report1" --height 42 --width 12 foo
$options
$options$report_name
[1] "report1"
$options$plot_height
[1] 42
$options$plot_width
[1] 12
$options$help
[1] FALSE
$args
[1] "foo"
Any ideas what might be going on here?
I am using R 3.3.0 and optparse_1.3.2 (getopt_1.20.0)
The -h flag is reserved by optparse (which is described as a feature of optparse which is not in getopt, from the getopt.R source file on Github):
Some features implemented in optparse package unavailable in getopt:
2. Automatic generation of an help option and printing of help text when encounters an "-h"
Therefore, when the user specifies -h, the sanity check for uniqueness of flags fails. The issue tracker does not seem to have any mention of the need to create a better error message for this case, however.
Finally, note that optparse seems to be invoking getopt, as they have the same author.
I want to call .exe program (spi_sl_6.exe) using a command of R (system), however I can't input parameters to the program using "system". The followwing is my command and parameters:system("D:\\working\spi_sl_6.exe")
I am searching for a long time on net. But no use. Please help or try to give some ideas how to achieve this. Thanks in advance.
This is using the Standardized Precipitation Index software from
http://drought.unl.edu/MonitoringTools/DownloadableSPIProgram.aspx.
This seems to give a working solution using Windows (but not without warnings!)
Fisrt download the software and example files
# Create directory to download software
mydir <- "C:\\Users\\david\\spi"
dir.create(mydir)
url <- "http://drought.unl.edu/archive/Programs/SPI"
download.file(file.path(url, "spi_sl_6.exe"), file.path(mydir, "spi_sl_6.exe"), mode="wb")
# Download example files
download.file(file.path(url, "SPI_samplefiles.zip"), file.path(mydir, "SPI_samplefiles.zip"))
# extract one example file, and write out
temp <- unzip(file.path(mydir, "SPI_samplefiles.zip"), "wymo.cor")
dat <- read.table(temp)
# Use this file as an example input
write.table(dat, file.path(mydir,"wymo.cor"), col.names = FALSE, row.names = FALSE)
From page 3 of the help file basic-spi-program-information.pdf at the above link the command line code should be of the form spi 3 6 12 <infile.dat >outfile.dat, however,
neither of the following worked (just from command line not in R), and various iterations of how to pass parameters.
C:\Users\david\spi\spi_sl_6 3 <C:\Users\david\spi\wymo.cor >C:\Users\david\spi\out.dat
cd C:\Users\david\spi && spi_sl_6 3 <wymo.cor >out.dat
However, using the accepted answer from Running .exe file with multiple parameters in c#
seems to work. That is again from the command line
cd C:\Users\david\spi && (echo 2 && echo 3 && echo 6 && echo wymo.cor && echo out1.dat) | spi_sl_6
So to run this in R you can wrap this in a shell (you will need to change the path to where you have saved the exe)
shell("cd C:\\Users\\david\\spi && (echo 2 && echo 3 && echo 6 && echo wymo.cor && echo out2.dat) | spi_sl_6", intern=TRUE)
out1.dat and out2.dat should be the same.
This throws warning messages, I think from the echo (in R but not from command line) but the output file is produced.
Suppose you can automate all the echo calls sligtly, so all you need to do is input the time parameters.
timez <- c(2, 3, 6)
stime <- paste("echo", timez, collapse =" && ")
infile <- "wymo.cor"
outfile <- "out3.dat"
spiCall <- paste("cd", mydir, "&& (" , stime, "&& echo", infile, "&& echo", outfile, " ) | spi_sl_6")
shell(spiCall)
You can construct the command using sprintf :
cmd_name <- "D:\\working\spi_sl_6.exe"
param1 <- "a"
param2 <- "b"
system2(sprintf("%s %s %s",cmd_name,param1,param2))
Or using system2( I prefer this option):
system2(cmd_name, args = c(param1,param2))
I have the following bash script in which an R script is called
#!/bin/bash
declare -x a=33
declare -x b=1
declare -x c=0
Rscript --vanilla MWE.R $a $b $c
echo $a $b $c
I want to modify the bash variables in the R script and return their modified values in the bash script because I am then passing the modified variables somewhere else. The R script is
#!/usr/bin/env Rscript
args = commandArgs(trailingOnly=TRUE)
Rb = as.numeric(args[2])
Rc = as.numeric(args[3])
Rb = Rb + 1
Rc = Rc + 1
args[2]=Rb
args[3]=Rc
print(c(args[1],args[2],args[3]))
However, the output of the print and echo respectively are:
[1] "33" "2" "1"
33 1 0
which shows that the new values aren't passed from R to bash. What am I doing wrong?
As Rscript does not allow environment variable manipulation you will need to capture the R output from the bash program.
One of the many possibilities is to use an array:
#!/bin/bash
declare a=33
declare b=1
declare c=0
declare -a RESULT
RESULT=($(Rscript --vanilla MWE.R $a $b $c))
a=${RESULT[1]}
b=${RESULT[2]}
c=${RESULT[3]}
I am running an R script via bash script and want to return the output of the R script to the bash script to keep working with it there.
The bash is sth like this:
#!/bin/bash
Rscript MYRScript.R
a=OUTPUT_FROM_MYRScript.R
do sth with a
and the R script is sth like this:
for(i in 1:5){
i
sink(type="message")
}
I want bash to work with one variable from R at the time, meaning: bash receives i=1 and works with that, when that task is done, receives i=2 and so on.
Any ideas how to do that?
One option is to make your R script executable with #!/usr/bin/env Rscript (setting the executable bit; e.g. chmod 0755 myrscript.r, chmod +x myrscript.r, etc...), and just treat it like any other command, e.g. assigning the results to an array variable below:
myrscript.r
#!/usr/bin/env Rscript
cat(1:5, sep = "\n")
mybashscript.sh
#!/bin/bash
RES=($(./myrscript.r))
for elem in "${RES[#]}"
do
echo elem is "${elem}"
done
nrussell$ ./mybashscript.sh
elem is 1
elem is 2
elem is 3
elem is 4
elem is 5
Here is MYRScript.R:
for(iter in 1:5) {
cat(iter, ' ')
}
and here is your bash script:
#!/bin/bash
r_output=`Rscript ~/MYRscript.R`
for iter in `echo $r_output`
do
echo Here is some output from R: $iter
done
Here is some output from R: 1
Here is some output from R: 2
Here is some output from R: 3
Here is some output from R: 4
Here is some output from R: 5
I need to build up long command lines in R and pass them to system(). I find it is very inconvenient to use paste0/paste function, or even sprintf function to build each command line. Is there a simpler way to do like this:
Instead of this hard-to-read-and-too-many-quotes:
cmd <- paste("command", "-a", line$elem1, "-b", line$elem3, "-f", df$Colum5[4])
or:
cmd <- sprintf("command -a %s -b %s -f %s", line$elem1, line$elem3, df$Colum5[4])
Can I have this:
cmd <- buildcommand("command -a %line$elem1 -b %line$elem3 -f %df$Colum5[4]")
For a tidyverse solution see https://github.com/tidyverse/glue. Example
name="Foo Bar"
glue::glue("How do you do, {name}?")
With version 1.1.0 (CRAN release on 2016-08-19), the stringr package has gained a string interpolation function str_interp() which is an alternative to the gsubfn package.
# sample data
line <- list(elem1 = 10, elem3 = 30)
df <- data.frame(Colum5 = 1:4)
# do the string interpolation
stringr::str_interp("command -a ${line$elem1} -b ${line$elem3} -f ${df$Colum5[4]}")
#[1] "command -a 10 -b 30 -f 4"
This comes pretty close to what you are asking for. When any function f is prefaced with fn$, i.e. fn$f, character interpolation will be performed replacing ... with the result of running ... as an R expression.
library(gsubfn)
cmd <- fn$identity("command -a `line$elem1` -b `line$elem3` -f `df$Colum5[4]`")
Here is a self contained reproducible example:
library(gsubfn)
# test inputs
line <- list(elem1 = 10, elem3 = 30)
df <- data.frame(Colum5 = 1:4)
fn$identity("command -a `line$elem1` -b `line$elem3` -f `df$Colum5[4]`")
## [1] "command -a 10 -b 30 -f 4"
system
Since any function can be used we could operate directly on the system call like this. We have used echo here to make it executable but any command could be used.
exitcode <- fn$system("echo -a `line$elem1` -b `line$elem3` -f `df$Colum5[4]`")
## -a 10 -b 30 -f 4
Variation
This variation would also work. fn$f also performs substitution of $whatever with the value of variable whatever. See ?fn for details.
with(line, fn$identity("command -a $elem1 -b $elem3 -f `df$Colum5[4]`"))
## [1] "command -a 10 -b 30 -f 4"
Another option would be to use whisker.render from https://github.com/edwindj/whisker which is a {{Mustache}} implementation in R. Usage example:
require(dplyr); require(whisker)
bedFile="test.bed"
whisker.render("processing {{bedFile}}") %>% print
Not really a string interpolation solution, but still a very good option for the problem is to use the processx package instead of system() and then you don't need to quote anything.
library(GetoptLong)
str = qq("region = (#{region[1]}, #{region[2]}), value = #{value}, name = '#{name}'")
cat(str)
qqcat("region = (#{region[1]}, #{region[2]}), value = #{value}, name = '#{name}'")
https://cran.r-project.org/web/packages/GetoptLong/vignettes/variable_interpolation.html