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

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

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

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


person Bryce Thomas    schedule 05.01.2013    source источник


Ответы (6)


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

В качестве примера приведу небольшой скрипт - назовите его "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

Изменить:

Не то чтобы я рекомендовал это, но ... используя комбинацию source() и sink(), вы можете заставить Rscript создать .Rout файл, подобный тому, который создается R CMD BATCH. Один из способов - создать небольшой сценарий R - назовите 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)

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

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

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

Edit2:
Вы можете запустить подробный сценарий Rscript и поместить подробный вывод в файл.

Rscript --verbose myScript.R 5 100 > myScript.Rout
person Josh O'Brien    schedule 05.01.2013
comment
У меня также сложилось впечатление, что R CMD BATCH - это реликвия. Что мне в нем нравится, так это то, что он создает файл .Rout, который включает не только выходные данные сценария, но также чередует входные команды / комментарии из файла сценария .R, создавшего этот вывод. - person Bryce Thomas; 05.01.2013
comment
Я слышу тебя. Это было (думаю, до сих пор!) Приятным аспектом R CMD BATCH. - person Josh O'Brien; 05.01.2013
comment
но я думаю, что вы можете добиться большего, чем R CMD BATCH, с knitr, например Rscript -e "knitr::stitch(commandArgs(TRUE)[1])" my_script.R (вы можете заменить stitch на stitch_rhtml или stitch_rmd, и вам нужно установить knitr из Github, поскольку я просто нашел ошибку в _8 _...) - person Yihui Xie; 05.01.2013
comment
@Yihui - Круто. Я посмотрю на это. У меня была аналогичная идея использовать Rscript для выполнения сценария, который использовал sink(outFile, split = TRUE), а затем source(srcFile, echo = TRUE) для создания эквивалента .Rout. Разместил его здесь на несколько минут, прежде чем откатиться назад, когда возникли проблемы, которые могут быть небезопасным способом использования sink(). Я с нетерпением жду возможности пройтись по коду в stitch. - person Josh O'Brien; 05.01.2013
comment
Просто чтобы добавить мою 0,02, также легко использовать перенаправление с терминала. Пример - Rscript myfile.R > path/to/mylog.Rout, и вместо вывода на стандартный вывод (экран) вывод файла сохраняется в вашем .Rout файле. - person James Pringle; 06.05.2014
comment
Чтобы добавить к @JamesPringle, я часто хочу, чтобы мой вывод выводился как на экран (для мониторинга в реальном времени), так и в файл (для просмотра позже). Я делаю Rscript myfile.R | tee mylog.Rout - person Heisenberg; 11.02.2015
comment
Замечательный комментарий @Yihui пришлось исправить вот так: r Rscript -e "library(knitr); knitr::stitch(commandArgs(TRUE)[1])" my_script.R - person petermeissner; 30.07.2015

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

Я поместил его код сюда:

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

$ 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!

person Alex A.    schedule 26.11.2013
comment
Важно отметить, что если аргументы имеют символьный тип, нет необходимости использовать одинарные / двойные кавычки. Например: R CMD BATCH '--args a = FolderName' test.R test.out & - person d2a2d; 01.12.2016
comment
Как упоминалось в сообщении Forester, --args - это ключ. Он также работает с R --no-save --no-restore --args a=1 < test.R и R --no-save --no-restore < test.R --args a=1 - person Dave; 08.03.2017
comment
Есть ли способ передать аргументы из командной строки в --args? Допустим, мы хотим выполнить цикл for в командной строке, а затем отправить его в строке --args. - person user2809432; 10.04.2019
comment
@ user2809432 Удалось ли вам в этом разобраться? У меня похожая проблема - person SpatialProgramming; 22.10.2020
comment
@ user2809432 Разобрать удалось! Используйте $ R вместо $ R CMD BATCH Т.е. ‹Code› для z в seq $x $y; do echo Выполняется задача $ z R --file = code / simulate_urban_rural.R --args $ z ›вывод завершен ‹/code› - person SpatialProgramming; 23.10.2020

Вам нужно поставить аргументы перед 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.
person Yihui Xie    schedule 05.01.2013
comment
Я замечаю, что если я делаю это таким образом и в сценарии использую args <- commandArgs(FALSE), а затем печатаю args, я получаю все аргументы, включая те, которые мне не принадлежат, например --restore, --save и т. Д. Если я использую commandArgs(TRUE), я не получаю аргументов вообще. Есть ли способ получить только мои собственные дополнительные аргументы? --args выглядит многообещающе, но мне не удалось заставить его работать ... - person Bryce Thomas; 05.01.2013
comment
Вы должны считать аргументы с конца (например, размер-2, размер-1, размер) - ваш всегда будет в конце. - person ynka; 24.10.2014

В вашем сценарии R с именем 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 
person user1563570    schedule 05.04.2013

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

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

Затем отправьте свой сценарий примерно так:

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"
person ClementWalter    schedule 16.03.2016

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

Вот 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)))
person Dagremu    schedule 15.12.2016