如何从R脚本读取命令行参数?

我有一个R脚本,我希望能够提供几个命令行参数(而不是在代码本身硬编码参数值)。该脚本运行在Windows系统上。

我找不到关于如何将命令行上提供的参数读到我的R脚本的信息。如果这不能做到,我会感到惊讶,所以也许我只是没有在我的谷歌搜索中使用最好的关键字…

有什么建议吗?

182963 次浏览

你需要的小(发音为“小r”)

Dirk将在大约15分钟后来详细说明;)

以下几点:

  1. 命令行参数为 可通过commandArgs()访问,因此 参见help(commandArgs)获取an 李概述。< / p > < / >

  2. 你可以在所有平台上使用Rscript.exe,包括Windows。它将支持commandArgs()little 可以移植到Windows,但目前仅在OS X和Linux上。

  3. CRAN上有两个附加包——getoptoptparse——它们都是为命令行解析而编写的。

新的替代方案已经出现,我推荐全心全意

德克的回答是是你需要的一切。这里有一个最小的可重复的例子。

我创建了两个文件:exmpl.batexmpl.R

  • < p > 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
    

    或者,使用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"

并在批处理脚本中作为%R_Script% <filename.r> <arguments>使用它

RScriptRterm的区别:

  • Rscript的语法更简单
  • Rscript自动选择x64上的体系结构(详情请参阅R安装和管理,2.6子架构)
  • 如果你想将命令写入输出文件,Rscript需要在.R文件中使用options(echo=TRUE)

把这个添加到你的脚本顶部:

args<-commandArgs(TRUE)

然后你可以引用传递的参数args[1]args[2]等。

然后运行

Rscript myscript.R arg1 arg2 arg3

如果参数是带空格的字符串,请用双引号括起来。

在bash中,您可以构造如下命令行:

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

你可以看到变量$z被bash shell替换为“10”,这个值被commandArgs拾取并输入到args[2],范围命令x=1:10被R成功执行,等等。

供您参考:有一个函数args(),它检索R个函数的参数,不要与名为args的参数向量混淆

Try library(getopt)…如果你想让事情变得更好。例如:

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();
}
如果你需要指定带有标志的选项(如-h,——help,——number=42等),你可以使用R包optparse(灵感来自Python): http://cran.r-project.org/web/packages/optparse/vignettes/optparse.pdf . < / p >

至少这是我理解你的问题的方式,因为我在寻找bash getopt,或perl getopt,或python argparse和optparse的等效程序时发现了这篇文章。

我只是把一个漂亮的数据结构和处理链放在一起来生成这种切换行为,不需要库。我相信它已经被实现过无数次了,并且在这个帖子中寻找例子-我想我应该分享一下。

我甚至不需要特别的标志(这里唯一的标志是调试模式,创建一个变量,我检查作为启动下游函数if (!exists(debug.mode)) {...} else {print(variables)})的条件。下面的标记检查lapply语句产生相同的结果:

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

其中args是从命令行参数中读入的变量(一个字符向量,例如,当你提供这些参数时,等价于c('--debug','--help'))

它可用于任何其他标志,你避免了所有的重复,没有库,所以没有依赖:

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

注意,在flag.details中,命令存储为字符串,然后用eval(parse(text = '...'))求值。对于任何严肃的脚本来说,Optparse显然都是可取的,但功能很少的代码有时也很好。

样例输出:

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


-h  --help  Display flag definitions

由于optparse已经在回答中提到了几次,并且它为命令行处理提供了一个全面的工具包,这里有一个简短的简化示例,说明如何使用它,假设输入文件存在:

< em >脚本。接待员:< / em >

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

给定任意文件blah.txt,包含23行。

在命令行中:

Rscript script.R -h 输出

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

__abc0 __abc2 __abc1

__abc0 __abc2 __abc1