Meneruskan argumen baris perintah ke R CMD BATCH


102

Saya telah menggunakan R CMD BATCH my_script.Rdari terminal untuk menjalankan Rskrip. Saya sekarang pada titik di mana saya ingin menyampaikan argumen ke perintah, tetapi mengalami beberapa masalah untuk membuatnya bekerja. Jika saya lakukan R CMD BATCH my_script.R blablamaka blablamenjadi file output, daripada diinterpretasikan sebagai argumen yang tersedia untuk skrip R.

Saya telah mencoba Rscript my_script.R blablayang tampaknya diteruskan blabladengan benar sebagai argumen, tetapi kemudian saya tidak mendapatkan my_script.Routfile output yang saya dapatkan R CMD BATCH(saya ingin .Routfile tersebut). Meskipun saya dapat mengarahkan output dari panggilan ke Rscriptnama file yang saya pilih, saya tidak akan mendapatkan perintah input R yang disertakan dalam file seperti R CMD BATCHhalnya di .Routfile.

Jadi, idealnya, saya mencari cara untuk mengirimkan argumen ke skrip R yang dieksekusi melalui R CMD BATCHmetode, meskipun akan senang dengan pendekatan yang digunakan Rscriptjika ada cara untuk membuatnya menghasilkan .Routfile yang sebanding .

Jawaban:


114

Kesan saya adalah itu R CMD BATCHsedikit peninggalan. Bagaimanapun, yang lebih baru Rscriptdapat dieksekusi (tersedia di semua platform), bersama dengan commandArgs()membuat pemrosesan argumen baris perintah cukup mudah.

Sebagai contoh, berikut ini skrip kecil - sebut saja "myScript.R":

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

Dan seperti inilah tampilan memanggilnya dari baris perintah

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

Edit:

Bukannya saya merekomendasikannya, tapi ... menggunakan kombinasi source()dan sink(), Anda bisa Rscriptmenghasilkan .Routfile seperti itu yang dihasilkan oleh R CMD BATCH. Salah satu caranya adalah dengan membuat skrip R kecil - sebut saja RscriptEcho.R - yang Anda panggil langsung dengan Rscript. Ini mungkin terlihat seperti ini:

## 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)

Untuk menjalankan skrip Anda yang sebenarnya, Anda kemudian akan melakukan:

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

yang akan dieksekusi myScript.Rdengan argumen yang disediakan dan memasukkan input, output, dan pesan yang diselingi ke dalam nama yang unik .Rout.

Edit2:
Anda dapat menjalankan Rscript secara verbosely dan menempatkan output verbose dalam sebuah file.

Rscript --verbose myScript.R 5 100 > myScript.Rout

4
Saya juga mendapatkan kesan R CMD BATCHsebagai peninggalan. Hal yang saya suka tentang itu adalah bahwa ia menghasilkan .Routfile yang tidak hanya menyertakan output skrip, tetapi juga menyisipkan perintah input / komentar dari .Rfile skrip yang menghasilkan output itu.
Bryce Thomas

1
Aku mendengarmu. Itu (saya kira masih!) Aspek yang bagus dari R CMD BATCH.
Josh O'Brien

5
tetapi saya pikir Anda dapat melakukan lebih baik daripada R CMD BATCHdengan knitr, misalnya Rscript -e "knitr::stitch(commandArgs(TRUE)[1])" my_script.R(Anda dapat mengganti stitchdengan stitch_rhtmlatau stitch_rmd, dan Anda perlu menginstal knitrdari Github karena saya baru saja menemukan bug di stitch...)
Yihui Xie

7
Hanya untuk menambahkan 0,02 saya, juga mudah menggunakan pengalihan dari terminal. Contohnya adalah Rscript myfile.R > path/to/mylog.Routdan alih-alih dicetak ke stdout (layar), output dari file disimpan dalam .Routfile Anda .
James Pringle

4
Untuk menambah @JamesPringle, saya sering ingin output saya dicetak di layar (untuk memantau secara real time) dan ke file (untuk dilihat nanti). Saya lakukanRscript myfile.R | tee mylog.Rout
Heisenberg

26

Setelah mencoba opsi yang dijelaskan di sini, saya menemukan posting ini dari Forester di r-blogger. Saya pikir ini adalah pilihan bersih untuk dipertimbangkan.

Saya meletakkan kodenya di sini:

Dari baris perintah

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

Dalam test.out

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

Terima kasih untuk Forester !


Penting untuk diperhatikan, jika argumen bertipe karakter, tidak perlu menggunakan tanda kutip tunggal / ganda. Misalnya: R CMD BATCH '--args a = FolderName' test.R test.out &
d2a2d

Seperti yang disebutkan dalam posting Forester, --argsadalah kuncinya. Ini juga bekerja dengan R --no-save --no-restore --args a=1 < test.RdanR --no-save --no-restore < test.R --args a=1
Dave

Apakah ada cara untuk meneruskan argumen dari baris perintah ke --args? Jadi katakanlah kita ingin melakukan perulangan for di baris perintah, dan kemudian mengirimkannya ke baris --args.
pengguna2809432

9

Dalam skrip R Anda, disebut test.R:

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

Dari baris perintah, jalankan:

R CMD BATCH -4 test.R

File keluaran Anda, test.Rout, akan menunjukkan bahwa argumen 4telah berhasil diteruskan ke 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

Anda perlu meletakkan argumen sebelumnya my_script.Rdan menggunakan -argumen, misalnya

R CMD BATCH -blabla my_script.R

commandArgs()akan menerima -blablasebagai string karakter dalam kasus ini. Lihat bantuan untuk detailnya:

$ 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
Saya melihat jika saya melakukannya dengan cara ini dan dalam penggunaan skrip args <- commandArgs(FALSE)dan kemudian mencetak args, saya berakhir dengan semua argumen, termasuk mereka yang bukan milikku, seperti --restore, --save, dll Jika saya menggunakan commandArgs(TRUE)saya mendapatkan tidak ada argumen sama sekali. Apakah ada cara untuk mendapatkan argumen tambahan saya sendiri? --argsterlihat menjanjikan, tapi saya belum bisa membuatnya bekerja ...
Bryce Thomas

Anda harus menghitung argumen dari akhir (misalnya ukuran-2, ukuran-1, ukuran) - argumen Anda akan selalu berada di akhir.
ynka

4

Saya menambahkan jawaban karena menurut saya solusi satu baris selalu bagus! Di atas myRscript.Rfile Anda , tambahkan baris berikut:

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

Kemudian kirimkan naskah Anda dengan sesuatu seperti:

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

Sebagai contoh:

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

Kemudian:

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

0

Berikut cara lain untuk memproses argumen baris perintah, menggunakan R CMD BATCH. Pendekatan saya, yang dibangun di atas jawaban sebelumnya di sini , memungkinkan Anda menentukan argumen pada baris perintah dan, dalam skrip R Anda, memberikan beberapa atau semuanya nilai default.

Ini file R, yang saya beri nama 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)

Di baris perintah, jika saya mengetik

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

maka dalam R kita akan memiliki a= 2dan b= c(2,5,6). Tetapi saya bisa, mengatakan, menghilangkan b, dan menambahkan argumen lain c:

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

Kemudian di R kita akan memiliki a= 2, b= c(1,1,1)(default), dan c= "hello".

Akhirnya, untuk kenyamanan kita bisa membungkus kode R dalam sebuah fungsi, selama kita berhati-hati dengan lingkungannya:

## 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)))
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.