【问题标题】:How can I read command line parameters from an R script?如何从 R 脚本中读取命令行参数?
【发布时间】:2017-03-16 18:11:54
【问题描述】:

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

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

有什么建议或建议吗?

【问题讨论】:

  • 你需要设置rscript可执行文件的位置

标签: command-line r parameters


【解决方案1】:

几点:

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

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

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

2015 年 11 月编辑:出现了新的替代品,我全心全意地推荐docopt。

【讨论】:

【解决方案2】:

Dirk's answer here 是您所需要的一切。这是一个最小的可重现示例。

我制作了两个文件:exmpl.bat 和 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
    

    或者,使用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% &lt;filename.r&gt; &lt;arguments&gt;

RScript 和 Rterm 之间的区别:

【讨论】:

    【解决方案3】:

    由于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"

    【讨论】:

      【解决方案4】:

      将此添加到脚本的顶部:

      args<-commandArgs(TRUE)
      

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

      然后运行

      Rscript myscript.R arg1 arg2 arg3
      

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

      【讨论】:

      • 这只在我使用 args
      • 在arg1之前需要--args吗?
      • @philcolbourn 没有
      【解决方案5】:

      我只是组合了一个很好的数据结构和处理链来生成这种切换行为,不需要库。我敢肯定它会被多次实现,并且遇到这个线程寻找示例 - 以为我会参与。

      我什至没有特别需要标志(这里唯一的标志是调试模式,创建一个变量,我检查它作为启动下游函数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 打印变量而不是执行函数 XYZ...
      
      -h --help 显示标志定义

      【讨论】:

        【解决方案6】:

        如果您需要指定带有标志的选项(如 -h、--help、--number=42 等),您可以使用 R 包 optparse(受 Python 启发): http://cran.r-project.org/web/packages/optparse/vignettes/optparse.pdf.

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

        【讨论】:

          【解决方案7】:

          在 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],并且R成功执行了range命令x=1:10,等等等等。

          【讨论】:

            【解决方案8】:

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

            【讨论】:

              【解决方案9】:

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

              【讨论】:

              • 几乎可以肯定不是这样。只有函数可以屏蔽函数。创建与函数同名的变量不会屏蔽函数。参考这个问答:stackoverflow.com/q/6135868/602276
              • 没错,它不会掩盖它。总的来说,我尽量避免使用 R 中已经存在的名称来命名函数和变量。
              【解决方案10】:

              你需要littler(读作'little r')

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2017-12-16
                • 1970-01-01
                • 2021-07-20
                • 2011-03-26
                • 2016-04-24
                相关资源
                最近更新 更多