Passing arguments to an R script from command lines

This post describes how to pass external arguments to R when calling a Rscript with a command line. The case study presented here is very simple: a Rscript is called which needs, as an input, a file name (a text file containing data which are loaded into R to be processed) and which can also accept an optional additional argument (an output file name: if this argument is not provided, the program supplies one by default).

Note: The program just loads a text file containing data, filters out non numeric variables and writes a text file with remaining numeric variables only.

R style

The most natural way to pass arguments from the command line is to use the function commandArgs. This function scans the arguments which have been supplied when the current R session was invoked. So creating a script named sillyScript.R which starts with

#!/usr/bin/env Rscript
args = commandArgs(trailingOnly=TRUE)

and running the following command line

Rscript --vanilla sillyScript.R iris.txt out.txt

will create a string vector args which contains the entries iris.txt and out.txt. Missing and default arguments can be handled this way:

# test if there is at least one argument: if not, return an error
if (length(args)==0) {
  stop("At least one argument must be supplied (input file).\n", call.=FALSE)
} else if (length(args)==1) {
  # default output file
  args[2] = "out.txt"
}

The simple use case described in the introduction thus gives

## program...
df = read.table(args[1], header=TRUE)
num_vars = which(sapply(df, class)=="numeric")
df_out = df[ ,num_vars]
write.table(df_out, file=args[2], row.names=FALSE)

Finally, the command lines

Rscript --vanilla sillyScript.R iris.txt out.txt

or

Rscript --vanilla sillyScript.R iris.txt

will both load the file iris.txt, filter out the non numeric variables and write the resulting data in out.txt. Whereas running

Rscript --vanilla sillyScript.R
Error: At least one argument must be supplied (input file).
Execution halted

python style

One package allows to obtain the same result in a python-like style: the package optparse. The package can be used to perform a similar task. Basically, the package contains the functions

  • make_option to declare options, their flags, types, default values and help messages;
  • OptionParser to read the arguments passed to the R script and parse_args to parse them according to what has been declared thanks to make_option.

The functions are used as follows:

#!/usr/bin/env Rscript
library("optparse")

option_list = list(
  make_option(c("-f", "--file"), type="character", default=NULL, 
              help="dataset file name", metavar="character"),
	make_option(c("-o", "--out"), type="character", default="out.txt", 
              help="output file name [default= %default]", metavar="character")
); 

opt_parser = OptionParser(option_list=option_list);
opt = parse_args(opt_parser);

which produces a list opt that contains all the arguments sorted by order of appearance in option_list and which can be called by their names as declared in this object: opt$file and opt$out. Then, managing null arguments is performed as follows:

if (is.null(opt$file)){
  print_help(opt_parser)
  stop("At least one argument must be supplied (input file).\n", call.=FALSE)
}

in which the function print_help print the help page of the option list as declared in the object option_list.

The remaining of the function is almost unchanged:

## program...
df = read.table(opt$file, header=TRUE)
num_vars = which(sapply(df, class)=="numeric")
df_out = df[ ,num_vars]
write.table(df_out, file=opt$out, row.names=FALSE)

If the entire script is saved in a file called yasrs.R,

Rscript --vanilla yasrs.R

will give

Usage: testScript.R [options]


Options:
  -f CHARACTER, --file=CHARACTER
		dataset file name

	-o CHARACTER, --out=CHARACTER
		output file name [default= out.txt]

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


Error: At least one argument must be supplied (input file).
Execution halted

and

Rscript --vanilla yasrs.R --help

will print the help

Usage: testScript.R [options]


Options:
  -f CHARACTER, --file=CHARACTER
		dataset file name

	-o CHARACTER, --out=CHARACTER
		output file name [default= out.txt]

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

and finally

Rscript --vanilla yasrs.R -f iris.txt

or

Rscript --vanilla yasrs.R -f iris.txt -o out.txt

will both create the file out.txt as described in the introduction of this post.

My dearest Céline, I hope that this post is explicit enough so that you can make your choice. Now you know that everything can be done with R, even this kind of map.
Additional note: in addition, a reader (thank you David) has pointed out that the script can be made executable using

chmod +x sillyScript.R

and then called with the command line:

./syllyScript.R iris.txt out.txt