【问题标题】:Set value of --args from within R session在 R 会话中设置 --args 的值
【发布时间】:2013-06-16 21:25:00
【问题描述】:

我想使用evaluate 包来模拟执行(大量)r 脚本,同时使用评估记录输出。 Evaluate 正是为了做到这一点而设计的,它几乎可以开箱即用。但是,在使用 Rscript 时,用户通过命令行 --args 传递参数,这些参数在 R 中使用 base::commandArgs 函数检索。

有什么明智的方法可以让我在正在运行的 R 会话中覆盖 --args 的值,这样使用 base::commandArgs() 的 R 脚本就可以按预期工作,而无需修改脚本本身?

【问题讨论】:

  • 为什么不在当前会话中设置参数?即在控制台输入args <- c(arge1,arg1,...)
  • 我希望它适用于 3rd 方 r-scripts。
  • 我不明白你的意思。我的意思是,您只需在脚本#args <- commandArgs(TRUE) 中注释一行,然后在控制台中定义args,然后再定义source('script_name')
  • 假设我有 10000000 个来自其他人的脚本,它们可能会或可能不会在某处使用 commandArgs,我想运行它们。
  • 我不能假设任何事情。如果您有 10000000 个脚本要运行您将此信息添加到您的问题中。以及如何测试 10000000 个脚本的参数。

标签: r evaluate cran rscript


【解决方案1】:

这是@spacedman 的答案,它是一个简单的基于 Rcpp 的实现。我们必须在向量上做一些体操,才能把它变成char** 格式:

#include "Rcpp.h"
#include "R_ext/RStartup.h"

// [[Rcpp::export]]
void setCmdArgs(std::vector<std::string> x) {
  std::vector<char*> vec(x.size());
  for (unsigned int i=0; i<x.size(); i++) 
    vec[i] = const_cast<char*>(x[i].c_str());
  R_set_command_line_arguments(x.size(), static_cast<char**>(&(vec[0])));
}

/*** R
setCmdArgs(c("hello", "world"))
commandArgs()
setCmdArgs(c("good", "bye", "my", "friend"))
commandArgs()
*/

如果您将其保存在文件中并通过一次调用 sourceCpp() 将其拉入,则 R 底部的 sn-p 也被执行:

R> sourceCpp("/tmp/spacedman.cpp")

R> setCmdArgs(c("hello", "world"))

R> commandArgs()
[1] "hello" "world"

R> setCmdArgs(c("good", "bye", "my", "friend"))

R> commandArgs()
[1] "good"   "bye"    "my"     "friend"
R> 

【讨论】:

    【解决方案2】:

    我钻研了 R 的肠子,想出了一些臭肠子来玩。

    命令行从C的argc/argv复制到一个全局C变量中,源码中有这个函数:

    void R_set_command_line_arguments(int argc, char **argv)
    

    所以我们需要一个小的 C 包装器来解决第一个参数不是指针的事实:

    #include "R.h"
    #include "R_ext/RStartup.h"
    void set_command(int *pargc, char **argv){
      R_set_command_line_arguments(*pargc, argv);
    }
    

    按常规方式编译:

    R CMD SHLIB setit.c
    

    加载,调用:

    > dyn.load("setit.so")
    > commandArgs()
    [1] "/usr/lib/R/bin/exec/R"
    > invisible(.C("set_command",as.integer(2),c("Foo","Bar")))
    > commandArgs()
    [1] "Foo" "Bar"
    

    从那时起,commandArgs() 将返回该向量,直到您更改它为止。

    【讨论】:

    • 即使这一切闻起来不是很好:) 但很高兴知道如何破解一些 R'C 代码。
    【解决方案3】:

    在脚本的顶部,您将commandArgs 设置为TRUE,如果您不在命令行上传递任何内容,则变量的长度将是0,因此请使用if 语句来分配一些当您实际上没有传递命令行参数时的值。如果您需要小心使用默认值,您可以在使用命令行参数的默认值时设置一个标志以打印消息。

    args <- commandArgs(TRUE)
    argDefault <- FALSE
    if( length(args) == 0 ){
       args <- whatever you want
       argDefault <- TRUE
    }
    res <- 2 * args[1]
    if( argDefault )
          simpleWarning(message="No command args were passed: Use of default values")  
    

    【讨论】:

    • @agstudy 感谢simpleWarning 的提示,我以前不知道这个。干杯!
    • 这并不能真正解决我的问题。我正在执行(很多)第三方提供的 r 脚本,这些脚本期望通过 commandArgs 输入。
    猜你喜欢
    • 2013-06-27
    • 1970-01-01
    • 2012-11-24
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-28
    相关资源
    最近更新 更多