Як я можу прочитати параметри командного рядка зі сценарію R?


281

У мене є скрипт R, для якого я хотів би мати можливість надати декілька параметрів командного рядка (а не значення параметрів жорсткого коду в самому коді). Сценарій працює в Windows.

Я не можу знайти інформацію про те, як зчитувати параметри, подані в командному рядку, до мого R-сценарію. Я був би здивований, якщо цього неможливо зробити, тому, можливо, я просто не використовую найкращих ключових слів у своєму пошуку Google ...

Якісь покажчики чи рекомендації?


вам потрібно встановити розташування виконуваного файлу

Відповіді:


209

Відповідь Дірка тут - все, що потрібно. Ось мінімально відтворюваний приклад.

Я зробив два файли: exmpl.batі 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
    

    Крім того, використовуючи 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)
    

Збережіть обидва файли в одному каталозі та запустіть exmpl.bat. В результаті ви отримаєте:

  • example.png з деяким сюжетом
  • exmpl.batch з усім, що було зроблено

Ви також можете додати змінну середовища %R_Script%:

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

і використовувати його у своїх пакетних сценаріях як %R_Script% <filename.r> <arguments>

Відмінності між RScriptта Rterm:


127

Кілька пунктів:

  1. Параметри командного рядка доступні через commandArgs(), тому дивіться help(commandArgs)огляд.

  2. Ви можете використовувати Rscript.exeна всіх платформах, включаючи Windows. Це підтримає commandArgs(). littler можна перенести в Windows, але зараз він працює лише в OS X та Linux.

  3. На CRAN є два додаткові пакети - getopt та optparse - які були написані для розбору командного рядка.

Редагувати в листопаді 2015 року: нові альтернативи з'явилися , і я від щирого серця рекомендую docopt .


2
і є argparse
gkcn

92

Додайте це до початку сценарію:

args<-commandArgs(TRUE)

Тоді ви можете звернутися до аргументів , переданих в якості args[1], і args[2]т.д.

Потім бігайте

Rscript myscript.R arg1 arg2 arg3

Якщо ваші аргументи - це рядки з пробілами, додайте їх до подвійних лапок.


7
Це спрацювало лише тоді, коли я використовував аргументи <-commandArgs (TRUE) (зверніть увагу на верхній регістр A).
Енді Вест

вам потрібні --арги перед arg1?
philcolbourn

@philcolbourn Ні
Chris_Rands

15

Спробуйте бібліотеку (getopt) ... якщо ви хочете, щоб речі були приємнішими. Наприклад:

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

вам потрібно littler (вимовляється «маленький r»)

Дірк зможе розробитись приблизно за 15 хвилин;)


11

Оскільки optparseв відповідях вже згадувалося кілька разів, і він пропонує всебічний набір для обробки командного рядка, ось короткий спрощений приклад того, як ви можете ним користуватися, припускаючи, що вхідний файл існує:

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

Дано довільний файл blah.txtз 23 рядками.

У командному рядку:

Rscript script.R -h виходи

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 виходи [1] "69"

Rscript script.R -n -f 5 blah.txt виходи [1] "115"


7

У bash ви можете побудувати командний рядок на зразок наступного:

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

Ви можете бачити, що змінна $zзамінена на bash shell на "10", і це значення підбирається commandArgsі вводиться в нього args[2], а команда діапазону x=1:10успішно виконується R і т.д. і т.д. і т.д.


4

FYI: є функція args (), яка витягує аргументи R-функцій, не плутати з вектором аргументів з ім'ям args


1
Це майже точно не так. Тільки функції можуть маскувати функції. Створення змінної з тим самим іменем функції не маскує функцію. Зверніться до цього питання і відповіді: stackoverflow.com/q/6135868/602276
Andrie

Щоправда, це не маскує. Я взагалі намагаюся уникати іменування функцій та змінних іменами, які вже є в Р.
Тім

1

Якщо вам потрібно вказати параметри з прапорами, (наприклад, -h, --help, - число = 42, тощо), ви можете використовувати R-пакет optparse (натхненний Python): http://cran.r-project.org /web/packages/optparse/vignettes/optparse.pdf .

Принаймні так я розумію ваше запитання, тому що я знайшов цю публікацію, шукаючи еквівалент bash getopt, або perl Getopt, або python argparse та optparse.


1

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

Мені навіть особливо не потрібні прапори (єдиний прапор тут - режим налагодження, створюючи змінну, яку я перевіряю як умову запуску функції вниз за течією if (!exists(debug.mode)) {...} else {print(variables)}). lapplyВиписки, що перевіряють прапор нижче, дають те саме, що:

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

де argsзмінна, зчитувана з аргументів командного рядка (символьний вектор, еквівалентний, c('--debug','--help')коли, наприклад, ви їх надаєте)

Він може використовуватись повторно для будь-якого іншого прапора, і ви уникаєте всіх повторень, і жодна бібліотека, так що не залежність:

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

Зауважте, що flag.detailsтут команди зберігаються як рядки, а потім оцінюються за допомогою eval(parse(text = '...')). Optparse, очевидно, бажаний для будь-якого серйозного сценарію, але код з мінімальною функціональністю теж іноді хороший.

Вибірка зразка:

$ Rscript check_mail.Rscript --help
--debug Друк змінних, а не виконання функції XYZ ...

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