Передача аргументов командной строки в R CMD BATCH

Я использовал R CMD BATCH my_script.R из терминала для выполнения R script. Я сейчас нахожусь в точке, где хотел бы передать аргумент команде, но у меня есть некоторые проблемы, связанные с ее работой. Если я делаю R CMD BATCH my_script.R blabla, тогда blabla становится выходным файлом, а не интерпретируется как аргумент, доступный для выполняемого R script.

Я пробовал Rscript my_script.R blabla, который, кажется, правильно передал blabla в качестве аргумента, но тогда я не получаю выходной файл my_script.Rout, который я получаю с помощью R CMD BATCH (я хочу, чтобы файл .Rout). Хотя я мог перенаправить вывод вызова на Rscript на имя файла по моему выбору, я бы не получил команды ввода R, включенные в файл, как R CMD BATCH в файле .Rout.

Итак, в идеале, я получаю способ передать аргументы в R script, выполняемые с помощью метода R CMD BATCH, хотя был бы доволен подходом, использующим Rscript, если есть способ сделать это создать сопоставимый файл .Rout.

Ответ 1

Мое впечатление, что R CMD BATCH - это немного реликт. В любом случае более свежий исполняемый файл Rscript (доступный на всех платформах) вместе с commandArgs() упрощает обработку аргументов командной строки.

В качестве примера, немного script - назовите его "myScript.R":

## myScript.R
args <- commandArgs(trailingOnly = TRUE)
rnorm(n=as.numeric(args[1]), mean=as.numeric(args[2]))

И вот что вызывает его из командной строки, как

> Rscript myScript.R 5 100
[1]  98.46435 100.04626  99.44937  98.52910 100.78853

Edit:

Не то, чтобы я рекомендовал его, но... используя комбинацию source() и sink(), вы могли бы получить Rscript для создания файла .Rout, подобного тому, который был создан R CMD BATCH. Одним из способов было бы создать небольшой R script - вызов it RscriptEcho.R - который вы вызываете напрямую с помощью Rscript. Это может выглядеть так:

## RscriptEcho.R
args <- commandArgs(TRUE)
srcFile <- args[1]
outFile <- paste0(make.names(date()), ".Rout")
args <- args[-1]

sink(outFile, split = TRUE)
source(srcFile, echo = TRUE)

Чтобы выполнить фактический script, вы должны:

Rscript RscriptEcho.R myScript.R 5 100
[1]  98.46435 100.04626  99.44937  98.52910 100.78853

который выполнит myScript.R с предоставленными аргументами и вставит чередующийся ввод, вывод и сообщения в уникально названный .Rout.

Ответ 2

После использования описанных здесь опций я нашел этот пост из Forester в r-bloggers. Я думаю, что это чистый вариант.

Я разместил его код здесь:

Из командной строки

$ R CMD BATCH --no-save --no-restore '--args a=1 b=c(2,5,6)' test.R test.out &

test.r

##First read in the arguments listed at the command line
args=(commandArgs(TRUE))

##args is now a list of character vectors
## First check to see if arguments are passed.
## Then cycle through each element of the list and evaluate the expressions.
if(length(args)==0){
    print("No arguments supplied.")
    ##supply default values
    a = 1
    b = c(1,1,1)
}else{
    for(i in 1:length(args)){
      eval(parse(text=args[[i]]))
    }
}

print(a*2)
print(b*3)

В test.out

> print(a*2)
[1] 2
> print(b*3)
[1]  6 15 18

Благодаря Forester!

Ответ 3

Вам нужно поставить аргументы перед my_script.R и использовать - для аргументов, например.

R CMD BATCH -blabla my_script.R

commandArgs() получит -blabla в качестве символьной строки в этом случае. Подробнее см. В справке:

$ R CMD BATCH --help
Usage: R CMD BATCH [options] infile [outfile]

Run R non-interactively with input from infile and place output (stdout
and stderr) to another file.  If not given, the name of the output file
is the one of the input file, with a possible '.R' extension stripped,
and '.Rout' appended.

Options:
  -h, --help        print short help message and exit
  -v, --version     print version info and exit
  --no-timing           do not report the timings
  --            end processing of options

Further arguments starting with a '-' are considered as options as long
as '--' was not encountered, and are passed on to the R process, which
by default is started with '--restore --save --no-readline'.
See also help('BATCH') inside R.

Ответ 4

В вашем R script, называемом test.R:

args <- commandArgs(trailingOnly = F)
myargument <- args[length(args)]
myargument <- sub("-","",myargument)
print(myargument)
q(save="no")

В командной строке выполните:

R CMD BATCH -4 test.R

Ваш выходной файл test.Rout покажет, что аргумент 4 был успешно передан в R:

cat test.Rout

> args <- commandArgs(trailingOnly = F)
> myargument <- args[length(args)]
> myargument <- sub("-","",myargument)
> print(myargument)
[1] "4"
> q(save="no")
> proc.time()
user  system elapsed 
0.222   0.022   0.236 

Ответ 5

Я добавляю ответ, потому что я думаю, что однострочное решение всегда хорошо! На вершине вашего файла myRscript.R добавьте следующую строку:

eval(parse(text=paste(commandArgs(trailingOnly = TRUE), collapse=";")))

Затем отправьте свой script с чем-то вроде:

R CMD BATCH [options] '--args arguments you want to supply' myRscript.R &

Например:

R CMD BATCH --vanilla '--args N=1 l=list(a=2, b="test") name="aname"' myscript.R &

Тогда:

> ls()
[1] "N"    "l"    "name"

Ответ 6

Здесь другой способ обработать аргументы командной строки, используя R CMD BATCH. Мой подход, основанный на более раннем ответе здесь, позволяет указать аргументы в командной строке и в вашем R script указать некоторые или все из них значения по умолчанию.

Здесь R файл, который я называю test.R:

defaults <- list(a=1, b=c(1,1,1)) ## default values of any arguments we might pass

## parse each command arg, loading it into global environment
for (arg in commandArgs(TRUE))
  eval(parse(text=arg))

## if any variable named in defaults doesn't exist, then create it
## with value from defaults
for (nm in names(defaults))
  assign(nm, mget(nm, ifnotfound=list(defaults[[nm]]))[[1]])

print(a)
print(b)

В командной строке, если я набираю

R CMD BATCH --no-save --no-restore '--args a=2 b=c(2,5,6)' test.R

то внутри R мы будем иметь a= 2 и b= c(2,5,6). Но я мог бы, например, опустить b и добавить еще один аргумент c:

R CMD BATCH --no-save --no-restore '--args a=2 c="hello"' test.R

Тогда в R будет a= 2, b= c(1,1,1) (по умолчанию) и c= "hello".

Наконец, для удобства мы можем обернуть R-код в функции, если мы будем осторожны в отношении среды:

## defaults should be either NULL or a named list
parseCommandArgs <- function(defaults=NULL, envir=globalenv()) {
  for (arg in commandArgs(TRUE))
    eval(parse(text=arg), envir=envir)

  for (nm in names(defaults))
    assign(nm, mget(nm, ifnotfound=list(defaults[[nm]]), envir=envir)[[1]], pos=envir)
}

## example usage:
parseCommandArgs(list(a=1, b=c(1,1,1)))