Передача аргументів командного рядка в R CMD BATCH


102

Я використовую 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файл.

Відповіді:


114

Моє враження, що 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 - називайте його 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

4
У мене також R CMD BATCHскладається враження , що це реліквія. Мені подобається в тому, що він створює .Routфайл, що включає не тільки вихід скрипту, але також перемежовує вхідні команди / коментарі з .Rфайлу сценарію, який видав цей вихід.
Брайс Томас

1
Я чую тебе. Це був (я думаю, все ще є!) Приємний аспект R CMD BATCH.
Josh O'Brien

5
але я думаю , що ви можете зробити краще , ніж R CMD BATCHз knitr, наприклад , Rscript -e "knitr::stitch(commandArgs(TRUE)[1])" my_script.R(ви можете замінити stitchз stitch_rhtmlабо stitch_rmd, і вам необхідно встановити knitrз Github , так як я тільки що знайшов помилку в stitch...)
Yihui Се

7
Тільки щоб додати мої 0,02, також легко використовувати перенаправлення з терміналу. Прикладом може бути те, що Rscript myfile.R > path/to/mylog.Routзамість того, щоб надрукувати в stdout (екран), вихідний файл зберігається у вашому .Routфайлі.
Джеймс Прінгл

4
Щоб додати до @JamesPringle, я часто хочу, щоб мої вихідні дані були надруковані на екрані (для моніторингу в режимі реального часу) та у файлі (щоб переглянути далі). Я роблюRscript myfile.R | tee mylog.Rout
Гейзенберг

26

Спробувавши описані тут варіанти, я знайшов цю публікацію від Forester у r-блогерів. Я думаю, що це чистий варіант для розгляду.

Я ставлю його код тут:

З командного рядка

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

Тест.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

Дякуємо Форестеру !


Важливо зазначити, що якщо аргументи мають характер типу, не потрібно використовувати одинарні / подвійні лапки. Напр .: R CMD BATCH '--арги a = FolderName' test.R test.out &
d2a2d

Як згадується у пості Форестера, --argsце головне. Він також працює з R --no-save --no-restore --args a=1 < test.RіR --no-save --no-restore < test.R --args a=1
Дейв

Чи є спосіб передати аргументи з командного рядка в --args? Отже, скажімо, що ми хочемо зробити цикл for в командному рядку, а потім відправити його в рядку --args.
user2809432

9

У вашому 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 

8

Ви повинні поставити аргументи раніше 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.

2
Я помічаю , якщо я роблю це так і при використанні сценарію , args <- commandArgs(FALSE)а потім роздрукувати арг, я в кінцевому підсумку всі аргументи, в тому числі і ті , які не мій, як --restore, --saveі т.д. Якщо я використовую commandArgs(TRUE)я не отримую ніяких аргументів взагалі. Чи є спосіб отримати лише власні додаткові аргументи? --argsвиглядає багатообіцяюче, але мені не вдалося змусити його працювати ...
Брайс Томас

Ви повинні порахувати аргументи з кінця (наприклад, розмір-2, розмір-1, розмір) - ваш завжди буде в кінці.
ynka

4

Я додаю відповідь, тому що думаю, що рішення в одному рядку завжди добре! Вгорі вашого 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"

0

Ось ще один спосіб обробки аргументів командного рядка, використовуючи 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)))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.