How can I read command line parameters from an R script?
Asked Answered
D

10

303

I've got a R script for which I'd like to be able to supply several command-line parameters (rather than hardcode parameter values in the code itself). The script runs on Windows.

I can't find info on how to read parameters supplied on the command-line into my R script. I'd be surprised if it can't be done, so maybe I'm just not using the best keywords in my Google search...

Any pointers or recommendations?

Dionnedionysia answered 27/1, 2010 at 23:40 Comment(1)
you need to set location of rscript executableDichlamydeous
K
220

Dirk's answer here is everything you need. Here's a minimal reproducible example.

I made two files: exmpl.bat and exmpl.R.

  • exmpl.bat:

    set R_Script="C:\Program Files\R-3.0.2\bin\RScript.exe"
    %R_Script% exmpl.R 2010-01-28 example 100 > exmpl.batch 2>&1
    

    Alternatively, using Rterm.exe:

    set R_TERM="C:\Program Files\R-3.0.2\bin\i386\Rterm.exe"
    %R_TERM% --no-restore --no-save --args 2010-01-28 example 100 < exmpl.R > exmpl.batch 2>&1
    
  • exmpl.R:

    options(echo=TRUE) # if you want see commands in output file
    args <- commandArgs(trailingOnly = TRUE)
    print(args)
    # trailingOnly=TRUE means that only your arguments are returned, check:
    # print(commandArgs(trailingOnly=FALSE))
    
    start_date <- as.Date(args[1])
    name <- args[2]
    n <- as.integer(args[3])
    rm(args)
    
    # Some computations:
    x <- rnorm(n)
    png(paste(name,".png",sep=""))
    plot(start_date+(1L:n), x)
    dev.off()
    
    summary(x)
    

Save both files in the same directory and start exmpl.bat. In the result you'll get:

  • example.png with some plot
  • exmpl.batch with all that was done

You could also add an environment variable %R_Script%:

"C:\Program Files\R-3.0.2\bin\RScript.exe"

and use it in your batch scripts as %R_Script% <filename.r> <arguments>

Differences between RScript and Rterm:

Kalli answered 28/1, 2010 at 11:47 Comment(0)
R
130

A few points:

  1. Command-line parameters are accessible via commandArgs(), so see help(commandArgs) for an overview.

  2. You can use Rscript.exe on all platforms, including Windows. It will support commandArgs(). littler could be ported to Windows but lives right now only on OS X and Linux.

  3. There are two add-on packages on CRAN -- getopt and optparse -- which were both written for command-line parsing.

Edit in Nov 2015: New alternatives have appeared and I wholeheartedly recommend docopt.

Roadway answered 28/1, 2010 at 1:11 Comment(1)
and there is argparseBlend
O
99

Add this to the top of your script:

args<-commandArgs(TRUE)

Then you can refer to the arguments passed as args[1], args[2] etc.

Then run

Rscript myscript.R arg1 arg2 arg3

If your args are strings with spaces in them, enclose within double quotes.

Overweening answered 28/1, 2010 at 12:52 Comment(3)
This only worked when I used args<-commandArgs(TRUE) (note the uppercase A).Tamar
do you need --args before arg1?Dismal
@Dismal NoAdvantage
M
19

Since optparse has been mentioned a couple of times in the answers, and it provides a comprehensive kit for command line processing, here's a short simplified example of how you can use it, assuming the input file exists:

script.R:

library(optparse)

option_list <- list(
  make_option(c("-n", "--count_lines"), action="store_true", default=FALSE,
    help="Count the line numbers [default]"),
  make_option(c("-f", "--factor"), type="integer", default=3,
    help="Multiply output by this number [default %default]")
)

parser <- OptionParser(usage="%prog [options] file", option_list=option_list)

args <- parse_args(parser, positional_arguments = 1)
opt <- args$options
file <- args$args

if(opt$count_lines) {
  print(paste(length(readLines(file)) * opt$factor))
}

Given an arbitrary file blah.txt with 23 lines.

On the command line:

Rscript script.R -h outputs

Usage: script.R [options] file


Options:
        -n, --count_lines
                Count the line numbers [default]

        -f FACTOR, --factor=FACTOR
                Multiply output by this number [default 3]

        -h, --help
                Show this help message and exit

Rscript script.R -n blah.txt outputs [1] "69"

Rscript script.R -n -f 5 blah.txt outputs [1] "115"

Matri answered 15/10, 2015 at 18:31 Comment(0)
E
15

Try library(getopt) ... if you want things to be nicer. For example:

spec <- matrix(c(
        'in'     , 'i', 1, "character", "file from fastq-stats -x (required)",
        'gc'     , 'g', 1, "character", "input gc content file (optional)",
        'out'    , 'o', 1, "character", "output filename (optional)",
        'help'   , 'h', 0, "logical",   "this help"
),ncol=5,byrow=T)

opt = getopt(spec);

if (!is.null(opt$help) || is.null(opt$in)) {
    cat(paste(getopt(spec, usage=T),"\n"));
    q();
}
Extrovert answered 27/12, 2012 at 15:1 Comment(0)
S
11

you need littler (pronounced 'little r')

Dirk will be by in about 15 minutes to elaborate ;)

Sandon answered 28/1, 2010 at 0:48 Comment(0)
D
8

In bash, you can construct a command line like the following:

$ z=10
$ echo $z
10
$ Rscript -e "args<-commandArgs(TRUE);x=args[1]:args[2];x;mean(x);sd(x)" 1 $z
 [1]  1  2  3  4  5  6  7  8  9 10
[1] 5.5
[1] 3.027650
$

You can see that the variable $z is substituted by bash shell with "10" and this value is picked up by commandArgs and fed into args[2], and the range command x=1:10 executed by R successfully, etc etc.

Deafmute answered 9/1, 2011 at 14:19 Comment(0)
S
4

FYI: there is a function args(), which retrieves the arguments of R functions, not to be confused with a vector of arguments named args

Spitzer answered 9/11, 2011 at 4:18 Comment(2)
This is almost certainly not the case. Only functions can mask functions. Creating a variable with the same name as a function does not mask the function. Refer to this question and answers: https://mcmap.net/q/101683/-in-r-what-exactly-is-the-problem-with-having-variables-with-the-same-name-as-base-r-functions/602276Adminicle
True, it doesn't mask it. Just in general, I try to avoid naming functions and variables with names that already exist in R.Spitzer
B
2

If you need to specify options with flags, (like -h, --help, --number=42, etc) you can use the R package optparse (inspired from Python): http://cran.r-project.org/web/packages/optparse/vignettes/optparse.pdf.

At least this how I understand your question, because I found this post when looking for an equivalent of the bash getopt, or perl Getopt, or python argparse and optparse.

Bridewell answered 20/5, 2014 at 15:33 Comment(0)
H
1

I just put together a nice data structure and chain of processing to generate this switching behaviour, no libraries needed. I'm sure it will have been implemented numerous times over, and came across this thread looking for examples - thought I'd chip in.

I didn't even particularly need flags (the only flag here is a debug mode, creating a variable which I check for as a condition of starting a downstream function if (!exists(debug.mode)) {...} else {print(variables)}). The flag checking lapply statements below produce the same as:

if ("--debug" %in% args) debug.mode <- T
if ("-h" %in% args || "--help" %in% args) 

where args is the variable read in from command line arguments (a character vector, equivalent to c('--debug','--help') when you supply these on for instance)

It's reusable for any other flag and you avoid all the repetition, and no libraries so no dependencies:

args <- commandArgs(TRUE)

flag.details <- list(
"debug" = list(
  def = "Print variables rather than executing function XYZ...",
  flag = "--debug",
  output = "debug.mode <- T"),
"help" = list(
  def = "Display flag definitions",
  flag = c("-h","--help"),
  output = "cat(help.prompt)") )

flag.conditions <- lapply(flag.details, function(x) {
  paste0(paste0('"',x$flag,'"'), sep = " %in% args", collapse = " || ")
})
flag.truth.table <- unlist(lapply(flag.conditions, function(x) {
  if (eval(parse(text = x))) {
    return(T)
  } else return(F)
}))

help.prompts <- lapply(names(flag.truth.table), function(x){
# joins 2-space-separatated flags with a tab-space to the flag description
  paste0(c(paste0(flag.details[x][[1]][['flag']], collapse="  "),
  flag.details[x][[1]][['def']]), collapse="\t")
} )

help.prompt <- paste(c(unlist(help.prompts),''),collapse="\n\n")

# The following lines handle the flags, running the corresponding 'output' entry in flag.details for any supplied
flag.output <- unlist(lapply(names(flag.truth.table), function(x){
  if (flag.truth.table[x]) return(flag.details[x][[1]][['output']])
}))
eval(parse(text = flag.output))

Note that in flag.details here the commands are stored as strings, then evaluated with eval(parse(text = '...')). Optparse is obviously desirable for any serious script, but minimal-functionality code is good too sometimes.

Sample output:

$ Rscript check_mail.Rscript --help
--debug Print  variables rather than executing function XYZ...

-h  --help  Display flag definitions
Hema answered 13/2, 2015 at 1:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.