2013-06-20 7 views
4

Я хотел бы использовать пакет evaluate для имитации выполнения (много) r-скриптов при записи выходов с использованием оценки. Evaluate предназначен для этого, и он работает почти из коробки. Однако при использовании Rscript пользователь передает аргументы через командную строку --args, которые извлекаются в R, используя функцию base::commandArgs.Установленное значение -args изнутри сеанса R

Есть ли какой-либо разумный способ, я могу переопределить значение --args из работающего сеанса R, чтобы сценарий R, использующий base::commandArgs(), работал бы так, как ожидалось, без необходимости изменять сам сценарий?

+0

Почему бы не указать свои аргументы в текущем сеансе? т.е. введите в консоль 'args <- c (arge1, arg1, ...)' – agstudy

+0

Я бы хотел, чтобы он работал для сторонних r-скриптов. – Jeroen

+0

Я не понимаю. Я имею в виду, что вы просто комментируете одну строку в своем скрипте '#args <- commandArgs (TRUE)', тогда вы определяете 'args' в своей консоли, а вы' source ('script_name') '. – agstudy

ответ

6

У меня была возможность вникать в кишки R и придумать какие-то вонючие кишки, с которыми можно было играть.

Командная строка копируется из ARGC языка C/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() вернет этот вектор, пока вы не измените его.

+0

, даже если все это пахнет не очень хорошо :), но хорошо знать, как взломать некоторый код R'C. – agstudy

+0

Awesome. Благодаря! – Jeroen

1

В верхней части вашего сценария вы установили 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") 
+2

@agstudy спасибо за подсказку с 'simpleWarning', я не знал об этом раньше. Ура! –

+1

На самом деле это не решает мою проблему. Я выполняю (много) сторонних r-скриптов, ожидающих ввода через 'commandArgs'. – Jeroen

10

Вот ответ @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>