【问题标题】:How to pass command-line arguments when calling source() on an R file within another R file如何在另一个 R 文件中的 R 文件上调用 source() 时传递命令行参数
【发布时间】:2013-01-25 16:05:24
【问题描述】:

在一个 R 文件中,我计划获取另一个支持读取两个命令行参数的 R 文件。这听起来像是一项微不足道的任务,但我在网上找不到解决方案。任何帮助表示赞赏。

【问题讨论】:

  • Dirk,我已经搜索过了,但在 StackOverflow 中找不到任何相关的。我看到你回答了许多与 R 相关的问题。感谢您的贡献。
  • 您对读取两个命令行参数的文件有任何控制权吗?
  • 您是指来自 bash shell 还是来自 R 控制台的命令行参数?
  • 您为什么要这样做? source(file) 的原因是将内容加载到您的工作区中。如果要执行源对象,最好在下一个命令中执行。
  • 回答 GSee 和 Seth 的 cmets。我编写了正在获取源的 R 脚本,它在 Bash shell 中使用。

标签: r


【解决方案1】:

我假设源脚本使用commandArgs 访问命令行参数?如果是这样,您可以在父脚本中覆盖 commandArgs 以在您正在采购的脚本中调用它时返回您想要的内容。看看它是如何工作的:

file_to_source.R

print(commandArgs())

main_script.R

commandArgs <- function(...) 1:3
source('file_to_source.R')

输出[1] 1 2 3

如果您的主脚本本身不接受任何命令行参数,您也可以只向该脚本提供参数。

【讨论】:

  • 重新定义 commandArgs() 函数看起来是一个聪明的解决方案。我试过了,它有效。
  • @MatthewPlourde 我不明白这是如何工作的,我必须将文件路径作为参数传递,而且我只有一个 r 脚本。你对父脚本和源脚本是什么意思?
  • @user4050 这个问题和答案涉及从另一个 R 脚本执行的情况。如果您从命令行运行 R 脚本,只需使用 commandArgs() 函数。
  • 这很好用,但是当从文件到源调用commandArgs 使用trailingOnly 参数时会失败。为了解决这个问题,我发现这通常更有用:commandArgs &lt;- function(...) 1:3 其中... 吸收任何未使用的参数。
  • 我认为这是一个非常糟糕的解决方案,因为你所做的就是重新定义commandArgs() 函数。
【解决方案2】:

最简单的解决方案是将source() 替换为system()paste。试试

arg1 <- 1
arg2 <- 2
system(paste("Rscript file_to_source.R", arg1, arg2))

【讨论】:

  • 你说得对,这很简单,但它不会将file_to_source.R 生成的对象带入globalenv()。为此,在我看来,您需要 Matthew Plourde 的技巧——重新定义 commandArgs,也许在调用 source() 后立即重新定义 rm() 您的版本。
  • 系统文档说“这个接口多年来变得相当复杂:请参阅 system2 以获得更便携和灵活的接口,推荐用于新代码。”
  • 难道不能定义一个定义了所需参数的环境,然后在该环境中获取脚本,以便找到正确的参数吗?然后你只需要通过另一个参数(向量类型)来扩展 source,它就会像魔术一样工作。
  • @U.Windl:如果我理解正确你的意思,那实际上已经有效......请参阅 GSee 的答案
【解决方案3】:

如果您有一个脚本来源另一个脚本,您可以在第一个脚本中定义可供来源脚本使用的变量。

> tmpfile <- tempfile()
> cat("print(a)", file=tmpfile)
> a <- 5
> source(tmpfile)
[1] 5

【讨论】:

  • 这是最直接的方法——对 R 新手很有用。调用脚本中设置的所有变量都可用于任何源脚本。 R 中强大的灵活性。
【解决方案4】:

@Matthew Plourde 答案的扩展版本。我通常做的是有一个 if 语句来检查命令行参数是否已经定义,否则读取它们。

此外,我尝试使用 argparse 库来读取命令行参数,因为它提供了更简洁的语法和更好的文档。

要获取的文件

 if (!exists("args")) {
         suppressPackageStartupMessages(library("argparse"))
         parser <- ArgumentParser()
         parser$add_argument("-a", "--arg1", type="character", defalt="a",
               help="First parameter [default %(defult)s]")
         parser$add_argument("-b", "--arg2", type="character", defalt="b",
               help="Second parameter [default %(defult)s]")
         args <- parser$parse_args()
 }

 print (args)

文件调用 source()

args$arg1 = "c" 
args$arg2 = "d"
source ("file_to_be_sourced.R")

c, d

【讨论】:

  • 我使用了一个轻微的变化,这样我只需要声明我想从默认值修改的参数:args &lt;- parser$parse_args(); if (exists('myargs')) { args &lt;- purrr::list_modify(args, !!!myargs) }
【解决方案5】:

这行得通:

# source another script with arguments
source_with_args <- function(file, ...){
  commandArgs <<- function(trailingOnly){
    list(...)
  }
  source(file)
}

source_with_args("sourcefile.R", "first_argument", "second_argument")

请注意,必须使用 &lt;&lt;- 而不是 &lt;- 重新定义内置的 commandArgs 函数。 据我了解,这使得它的范围超出了定义它的函数source_with_args()

【讨论】:

  • 请注意,上面的代码可以很好地执行我想要的操作(将参数传递给源 R 脚本,就好像它们是命令行参数一样。)现在当我尝试重复时,我收到了这个错误: “无法更改 'commandArgs' 的锁定绑定的值 任何 cmets 关于为什么这最初有效但现在无效?
  • get error =>
  • 不适合我。我正在使用 R 4.1.2
【解决方案6】:

我在这里测试了一些替代方案,我最终得到了这个:

文件调用源:

source_with_args <- function(file, ...){
  system(paste("Rscript", file, ...))
}
source_with_args(
  script_file,
  paste0("--data=", data_processed_file),
  paste0("--output=", output_file)
)

文件来源:

  library(optparse)
  option_list = list(
    make_option(
      c("--data"),
      type="character",
      default=NULL,
      help="input file",
      metavar="filename"
    ),
    make_option(
      c("--output"),
      type="character",
      default=NULL,
      help="output file [default= %default]",
      metavar="filename"
    )
  )
  opt_parser = OptionParser(option_list=option_list)
  data_processed_file <- opt$data
  oputput_file <- opt$output
  if(is.null(data_processed_file) || is.null(oputput_file)){
    stop("Required information is missing")
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-16
    • 2023-04-04
    • 2011-09-28
    • 2019-05-21
    • 2016-01-18
    • 1970-01-01
    • 2012-11-27
    • 2012-02-12
    相关资源
    最近更新 更多