Как я могу прочитать параметры командной строки из сценария R?

246

У меня есть R script, для которого я хотел бы предоставить несколько параметров командной строки (а не значения параметра жесткого кода в самом коде). script работает в Windows.

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

Любые указатели или рекомендации?

  • 0
    вам нужно указать местоположение исполняемого файла rscript
Теги:
command-line
parameters

10 ответов

183
Лучший ответ

Dirk answer here - это все, что вам нужно. Здесь приведен минимальный воспроизводимый пример.

Я сделал два файла: 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:

  • RScript имеет более простой синтаксис
  • RScript автоматически выбирает архитектуру на x64 (подробнее см. R Installation and Administration, 2.6 Sub-architecture)
  • RScript требуется options(echo=TRUE) в .R файле, если вы хотите записать команды в выходной файл
115

Несколько точек:

  • Параметры командной строки: доступный через commandArgs(), поэтому см. help(commandArgs) для обзор.

  • Вы можете использовать Rscript.exe на всех платформах, включая Windows. Он будет поддерживать commandArgs(). littler можно портировать в Windows, но он живет прямо сейчас только на OS X и Linux.

  • В CRAN есть два дополнительных пакета - getopt и optparse - оба они были написаны для разбора командной строки.

Изменить в ноябре 2015: появились новые альтернативы, и я всем сердцем рекомендую doctopt.

  • 8
    +1 за указатель на пакет optparse .
  • 2
    и есть argparse
82

Добавьте это в начало script:

args<-commandArgs(TRUE)

Затем вы можете обратиться к аргументам, переданным как args[1], args[2] и т.д.

Затем запустите

Rscript myscript.R arg1 arg2 arg3

Если ваши аргументы являются строками с пробелами в них, заключите их в двойные кавычки.

  • 7
    Это работало только когда я использовал args <-commandArgs (TRUE) (обратите внимание на верхний регистр A).
  • 0
    вам нужно --args до arg1?
Показать ещё 1 комментарий
12

Попробуйте библиотеку (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();
}
8

вам нужно littler (произносится как "little r" )

Дирк будет примерно через 15 минут, чтобы разработать;)

  • 24
    Я опоздал на семь минут. Должно быть, было плохое движение на Intertubes.
  • 2
    либо это, либо вы стареете. ;)
Показать ещё 1 комментарий
4

Так как 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"

4

В 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 успешно и т.д. и т.д.

3

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

  • 1
    Это почти наверняка не так. Только функции могут маскировать функции. Создание переменной с тем же именем, что и у функции, не маскирует функцию. Обратитесь к этому вопросу и ответам: stackoverflow.com/q/6135868/602276
  • 0
    Правда, это не маскирует это. В общем, я стараюсь избегать именования функций и переменных с именами, которые уже существуют в R.
0

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

Мне даже не нужны флаги (единственный флаг здесь - это режим отладки, создающий переменную, которую я проверяю как условие запуска нисходящей функции 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, очевидно, желательно для любого серьезного script, но код минимальной функциональности тоже очень хорош.

Пример вывода:

  $ Rscript check_mail.Rscript --help
--debug Печать переменных, а не выполнение функции XYZ...

-h --help Определение флагов отображения
0

Если вам нужно указать опции с флагами (например, -h, --help, --number = 42 и т.д.), вы можете использовать оп пакетный пакет R (вдохновленный Python): http://cran.r-project.org/web/packages/optparse/vignettes/optparse.pdf.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню