5

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

是否有任何明智的方法可以覆盖--args正在运行的 R 会话中的值,以便使用的 R 脚本base::commandArgs()可以按预期工作而无需修改脚本本身?

4

3 回答 3

11

这是@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 代码段也会执行:

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> 
于 2013-06-20T20:02:06.250 回答
7

我钻研了 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()将返回该向量,直到您更改它。

于 2013-06-20T18:53:54.467 回答
1

在脚本的顶部,您设置commandArgsTRUE,如果您没有在命令行上传递任何内容,则该变量将是有长度的,因此当您实际上没有传递命令行参数时,请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")  
于 2013-06-20T07:28:29.600 回答