Bagaimana saya bisa membaca parameter baris perintah dari skrip R?


281

Saya punya skrip R yang ingin saya berikan beberapa parameter baris perintah (daripada nilai parameter hardcode dalam kode itu sendiri). Script berjalan pada Windows.

Saya tidak dapat menemukan info tentang cara membaca parameter yang disediakan pada command-line ke dalam skrip R. Saya akan terkejut jika itu tidak dapat dilakukan, jadi mungkin saya tidak menggunakan kata kunci terbaik di pencarian Google saya ...

Adakah petunjuk atau rekomendasi?


Anda perlu mengatur lokasi rscript dapat dieksekusi

Jawaban:


209

Jawaban Dirk di sini adalah semua yang Anda butuhkan. Berikut adalah contoh minimal yang dapat direproduksi.

Saya membuat dua file: exmpl.batdan exmpl.R.

  • exmpl.bat:

    set R_Script="C:\Program Files\R-3.0.2\bin\RScript.exe"
    %R_Script% exmpl.R 2010-01-28 example 100 > exmpl.batch 2>&1

    Atau, gunakan Rterm.exe:

    set R_TERM="C:\Program Files\R-3.0.2\bin\i386\Rterm.exe"
    %R_TERM% --no-restore --no-save --args 2010-01-28 example 100 < exmpl.R > exmpl.batch 2>&1
  • exmpl.R:

    options(echo=TRUE) # if you want see commands in output file
    args <- commandArgs(trailingOnly = TRUE)
    print(args)
    # trailingOnly=TRUE means that only your arguments are returned, check:
    # print(commandArgs(trailingOnly=FALSE))
    
    start_date <- as.Date(args[1])
    name <- args[2]
    n <- as.integer(args[3])
    rm(args)
    
    # Some computations:
    x <- rnorm(n)
    png(paste(name,".png",sep=""))
    plot(start_date+(1L:n), x)
    dev.off()
    
    summary(x)

Simpan kedua file di direktori yang sama dan mulai exmpl.bat. Dalam hasilnya Anda akan mendapatkan:

  • example.png dengan beberapa plot
  • exmpl.batch dengan semua yang dilakukan

Anda juga bisa menambahkan variabel lingkungan %R_Script%:

"C:\Program Files\R-3.0.2\bin\RScript.exe"

dan menggunakannya dalam skrip batch Anda sebagai %R_Script% <filename.r> <arguments>

Perbedaan antara RScriptdan Rterm:

  • Rscript memiliki sintaksis yang lebih sederhana
  • Rscriptsecara otomatis memilih arsitektur pada x64 (lihat R Instalasi dan Administrasi, 2.6 Sub-arsitektur untuk perincian)
  • Rscriptperlu options(echo=TRUE)dalam file .R jika Anda ingin menulis perintah ke file output

127

Beberapa poin:

  1. Parameter baris perintah dapat diakses melalui commandArgs(), jadi lihat help(commandArgs)ikhtisar.

  2. Anda dapat menggunakan Rscript.exesemua platform, termasuk Windows. Itu akan mendukung commandArgs(). littler dapat di-porting ke Windows tetapi sekarang hanya hidup di OS X dan Linux

  3. Ada dua paket tambahan pada CRAN - getopt dan optparse - yang keduanya ditulis untuk penguraian baris perintah.

Edit pada Nov 2015: Alternatif baru telah muncul dan saya dengan sepenuh hati merekomendasikan docopt .


2
dan ada argparse
gkcn

92

Tambahkan ini ke bagian atas skrip Anda:

args<-commandArgs(TRUE)

Kemudian Anda bisa merujuk ke argumen yang diteruskan sebagai args[1],args[2] dll.

Lalu lari

Rscript myscript.R arg1 arg2 arg3

Jika argumen Anda adalah string dengan spasi di dalamnya, sertakan dalam tanda kutip ganda.


7
Ini hanya berfungsi ketika saya menggunakan args <-commandArgs (TRUE) (perhatikan huruf besar A).
Andy West

apakah Anda memerlukan --args sebelum arg1?
philcolbourn

@philcolbourn No
Chris_Rands

15

Coba pustaka (getopt) ... jika Anda ingin sesuatu menjadi lebih baik. Sebagai contoh:

spec <- matrix(c(
        'in'     , 'i', 1, "character", "file from fastq-stats -x (required)",
        'gc'     , 'g', 1, "character", "input gc content file (optional)",
        'out'    , 'o', 1, "character", "output filename (optional)",
        'help'   , 'h', 0, "logical",   "this help"
),ncol=5,byrow=T)

opt = getopt(spec);

if (!is.null(opt$help) || is.null(opt$in)) {
    cat(paste(getopt(spec, usage=T),"\n"));
    q();
}

11

Anda membutuhkan littler (dilafalkan 'little r')

Dirk akan selesai sekitar 15 menit untuk menguraikan;)


11

Karena optparsetelah disebutkan beberapa kali dalam jawaban, dan ini memberikan kit yang komprehensif untuk pemrosesan baris perintah, berikut adalah contoh singkat yang disederhanakan tentang bagaimana Anda dapat menggunakannya, dengan asumsi file input ada:

script.R:

library(optparse)

option_list <- list(
  make_option(c("-n", "--count_lines"), action="store_true", default=FALSE,
    help="Count the line numbers [default]"),
  make_option(c("-f", "--factor"), type="integer", default=3,
    help="Multiply output by this number [default %default]")
)

parser <- OptionParser(usage="%prog [options] file", option_list=option_list)

args <- parse_args(parser, positional_arguments = 1)
opt <- args$options
file <- args$args

if(opt$count_lines) {
  print(paste(length(readLines(file)) * opt$factor))
}

Diberikan file sewenang-wenang blah.txtdengan 23 baris.

Di baris perintah:

Rscript script.R -h output

Usage: script.R [options] file


Options:
        -n, --count_lines
                Count the line numbers [default]

        -f FACTOR, --factor=FACTOR
                Multiply output by this number [default 3]

        -h, --help
                Show this help message and exit

Rscript script.R -n blah.txt output [1] "69"

Rscript script.R -n -f 5 blah.txt output [1] "115"


7

Di bash, Anda bisa membuat baris perintah seperti berikut:

$ z=10
$ echo $z
10
$ Rscript -e "args<-commandArgs(TRUE);x=args[1]:args[2];x;mean(x);sd(x)" 1 $z
 [1]  1  2  3  4  5  6  7  8  9 10
[1] 5.5
[1] 3.027650
$

Anda dapat melihat bahwa variabel $zdiganti oleh bash shell dengan "10" dan nilai ini diambil oleh commandArgsdan dimasukkan ke dalam args[2], dan perintah rentang x=1:10dieksekusi oleh R berhasil, dll.


4

FYI: ada fungsi args (), yang mengambil argumen fungsi R, jangan dikacaukan dengan vektor argumen bernama args


1
Ini hampir pasti bukan itu masalahnya. Hanya fungsi yang bisa menutupi fungsi. Membuat variabel dengan nama yang sama dengan suatu fungsi tidak menutupi fungsi tersebut. Lihat pertanyaan dan jawaban ini: stackoverflow.com/q/6135868/602276
Andrie

Benar, itu tidak menutupi itu. Secara umum, saya mencoba menghindari fungsi penamaan dan variabel dengan nama yang sudah ada di R.
Tim


1

Saya hanya mengumpulkan struktur data yang bagus dan rantai pemrosesan untuk menghasilkan perilaku switching ini, tidak perlu perpustakaan. Saya yakin itu akan diimplementasikan berkali-kali, dan menemukan utas ini mencari contoh - pikir saya akan ikut campur.

Saya bahkan tidak terlalu membutuhkan flag (satu-satunya flag di sini adalah mode debug, membuat variabel yang saya periksa sebagai syarat untuk memulai fungsi hilir if (!exists(debug.mode)) {...} else {print(variables)}). lapplyPernyataan pemeriksaan bendera di bawah ini menghasilkan yang sama dengan:

if ("--debug" %in% args) debug.mode <- T
if ("-h" %in% args || "--help" %in% args) 

di mana argsvariabel dibaca dari argumen baris perintah (vektor karakter, setara denganc('--debug','--help') ketika Anda memasok ini misalnya)

Ini dapat digunakan kembali untuk bendera lain dan Anda menghindari semua pengulangan, dan tidak ada perpustakaan sehingga tidak ada ketergantungan:

args <- commandArgs(TRUE)

flag.details <- list(
"debug" = list(
  def = "Print variables rather than executing function XYZ...",
  flag = "--debug",
  output = "debug.mode <- T"),
"help" = list(
  def = "Display flag definitions",
  flag = c("-h","--help"),
  output = "cat(help.prompt)") )

flag.conditions <- lapply(flag.details, function(x) {
  paste0(paste0('"',x$flag,'"'), sep = " %in% args", collapse = " || ")
})
flag.truth.table <- unlist(lapply(flag.conditions, function(x) {
  if (eval(parse(text = x))) {
    return(T)
  } else return(F)
}))

help.prompts <- lapply(names(flag.truth.table), function(x){
# joins 2-space-separatated flags with a tab-space to the flag description
  paste0(c(paste0(flag.details[x][[1]][['flag']], collapse="  "),
  flag.details[x][[1]][['def']]), collapse="\t")
} )

help.prompt <- paste(c(unlist(help.prompts),''),collapse="\n\n")

# The following lines handle the flags, running the corresponding 'output' entry in flag.details for any supplied
flag.output <- unlist(lapply(names(flag.truth.table), function(x){
  if (flag.truth.table[x]) return(flag.details[x][[1]][['output']])
}))
eval(parse(text = flag.output))

Perhatikan bahwa di flag.detailssini perintah disimpan sebagai string, kemudian dievaluasi dengan eval(parse(text = '...')). Optparse jelas diinginkan untuk skrip serius, tetapi kode fungsionalitas minimal juga baik.

Output sampel:

$ Rscript check_mail.Rscript --help
--debug Cetak variabel daripada menjalankan fungsi XYZ ...

-h --help Menampilkan definisi flag
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.