提问



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


我无法找到有关如何将命令行中提供的参数读入我的R脚本的信息。如果不能完成,我会感到惊讶,所以也许我只是没有在Google搜索中使用最好的关键字...


任何指针或建议?

最佳参考


德克在这里的答案就是你需要的一切。这是一个可重复性最小的例子。


我做了两个文件:exmpl.batexmpl.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
    


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



将两个文件保存在同一目录中并启动exmpl.bat。结果你会得到:



  • example.png带有一些情节

  • exmpl.batch完成所有工作



您还可以添加环境变量%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)


其它参考1


几点:[54]



  1. 命令行参数是
    可以通过commandArgs()访问,所以
    help(commandArgs)
    概述。

  2. 您可以在所有平台上使用Rscript.exe,包括Windows。它将支持commandArgs()。 littler可以移植到Windows,但现在只能在OS X和Linux上使用。[55]

  3. CRAN上有两个附加软件包 - getopt和optparse - 它们都是为命令行解析而编写的。[56] [57]



2015年11月编辑:新的替代方案已经出现,我全心全意推荐docopt。[58]

其它参考2


将其添加到脚本的顶部:


args<-commandArgs(TRUE)


然后你可以参考作为args[1]args[2]等传递的参数。


然后跑


Rscript myscript.R arg1 arg2 arg3


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

其它参考3


尝试库(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();
}

其它参考4


你需要更小的(发音为little r)[59]


德克将在大约15分钟内完成;)

其它参考5


由于optparse已在答案中多次提及,并且它提供了一个用于命令行处理的综合工具包,这里是一个简短的示例,说明如何使用它,假设输入文件存在:


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


给定23行的任意文件blah.txt


在命令行上:


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


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


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

其它参考6


在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成功执行等等

其它参考7


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

其它参考8


如果你需要指定带有flags的选项(比如-h, - help, - number=42等),你可以使用R包optparse(灵感来自Python):
http://cran.r-project.org/web/packages/optparse/vignettes/optparse.pdf.[60]


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

其它参考9


我只是将一个很好的数据结构和处理链组合在一起来生成这种切换行为,不需要库。我确信它已经实施了很多次,并且遇到了这个寻找示例的线程 - 我以为我会插手。


我甚至没有特别需要标志(这里唯一的标志是调试模式,创建一个变量,我检查它作为启动下游函数的条件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