¿Cómo puedo leer los parámetros de la línea de comandos de un script R?


Tengo un script R para el que me gustaría poder suministrar varios parámetros de línea de comandos (en lugar de valores de parámetros de código duro en el código mismo). El script se ejecuta en Windows.

No puedo encontrar información sobre cómo leer los parámetros suministrados en la línea de comandos en mi script R. Me sorprendería si no se puede hacer, así que tal vez no estoy usando las mejores palabras clave en mi búsqueda en Google...

¿Algún consejo o recomendación?

Author: monch1962, 2010-01-28

10 answers

La respuesta de Dirk aquí es todo lo que necesitas. Aquí hay un ejemplo reproducible mínimo.

Hice dos archivos: exmpl.bat y 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
    

    Alternativamente, usando 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)
    

Guarde ambos archivos en el mismo directorio e inicie exmpl.bat. En el resultado obtendrás:

  • example.png con alguna parcela
  • exmpl.batch con todo lo que se hizo

Usted también podría agregar una variable de entorno %R_Script%:

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

Y úselo en sus scripts por lotes como %R_Script% <filename.r> <arguments>

Diferencias entre RScript y Rterm:

  • Rscript tiene una sintaxis más simple
  • Rscript elige automáticamente la arquitectura en x64 (ver R Instalación y Administración, subarquitectura 2.6 para más detalles)
  • Rscript necesita options(echo=TRUE) en el.Archivo R si desea escribir los comandos en el archivo de salida
 194
Author: Marek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-02 14:18:54

Algunos puntos:

  1. Los parámetros de la línea de comandos son accesible a través de commandArgs(), so véase help(commandArgs) para una descripción.

  2. Puede usar Rscript.exe en todas las plataformas, incluyendo Windows. Soportará commandArgs(). littler podría ser portado a Windows, pero vive ahora solo en OS X y Linux.

  3. Hay dos paquetes para agregar en CRAN -- getopt y optparse -- que fueron escritas para la línea de comandos analizar.

Editar en noviembre de 2015: Han aparecido nuevas alternativas y Yo de todo corazón recomiendo docopt.

 117
Author: Dirk Eddelbuettel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-01 13:17:37

Añade esto al principio de tu script:

args<-commandArgs(TRUE)

Entonces puede referirse a los argumentos pasados como args[1], args[2] etc.

Luego ejecuta

Rscript myscript.R arg1 arg2 arg3

Si sus args son cadenas con espacios en ellas, encierre entre comillas dobles.

 82
Author: Hrishi Mittal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-27 13:10:20

Prueba la biblioteca(getopt) ... si quieres que las cosas sean más agradables. Por ejemplo:

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();
}
 12
Author: Erik Aronesty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-27 15:01:48

Necesitas más pequeño (pronunciado 'pequeña r')

Dirk estará en unos 15 minutos para elaborar;)

 8
Author: JD Long,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-28 00:48:54

Dado que optparse ha sido mencionado un par de veces en las respuestas, y proporciona un kit completo para el procesamiento de la línea de comandos, aquí hay un breve ejemplo simplificado de cómo puede usarlo, asumiendo que el archivo de entrada existe:

guión.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))
}

Dado un fichero arbitrario blah.txt con 23 líneas.

En la línea de comandos:

Rscript script.R -h salidas

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 productos [1] "69"

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

 7
Author: Megatron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-15 18:31:12

En bash, puedes construir una línea de comandos como la siguiente:

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

Puede ver que la variable $z es sustituida por bash shell con "10" y este valor es recogido por commandArgs y alimentado en args[2], y el comando range x=1:10 ejecutado por R con éxito, etc etc.

 5
Author: TTW,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-27 21:18:53

Para su información: hay una función args (), que recupera los argumentos de las funciones R, que no debe confundirse con un vector de argumentos llamado args

 3
Author: Tim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-10 02:43:18

Si necesita especificar opciones con banderas, (como-h, help help, number number=42, etc.) puede usar el paquete R optparse (inspirado en Python): http://cran.r-project.org/web/packages/optparse/vignettes/optparse.pdf .

Al menos así entiendo tu pregunta, porque encontré este post cuando buscaba un equivalente de bash getopt, o perl Getopt, o python argparse y optparse.

 0
Author: TheBinturonGggh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-20 15:33:46

Acabo de armar una buena estructura de datos y cadena de procesamiento para generar este comportamiento de conmutación, no se necesitan bibliotecas. Estoy seguro de que se ha implementado en numerosas ocasiones, y me encontré con este hilo en busca de ejemplos - pensé que me gustaría contribuir.

Ni siquiera necesitaba banderas (la única bandera aquí es un modo de depuración, creando una variable que compruebo como condición para iniciar una función descendente if (!exists(debug.mode)) {...} else {print(variables)}). El flag checking lapply de abajo produce la igual que:

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

Donde args es la variable leída desde los argumentos de la línea de comandos (un vector de caracteres, equivalente a c('--debug','--help') cuando proporciona estos, por ejemplo)

Es reutilizable para cualquier otra bandera y se evita toda la repetición, y no hay bibliotecas por lo que no hay dependencias:

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

Tenga en cuenta que en flag.details aquí los comandos se almacenan como cadenas, luego se evalúan con eval(parse(text = '...')). Optparse es obviamente deseable para cualquier script serio, pero el código de funcionalidad mínima también es bueno a veces.

Salida de muestra:

$ Rscript check_mail.Rscript --help
--debug Print  variables rather than executing function XYZ...

-h  --help  Display flag definitions
 0
Author: Louis Maddox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-13 03:13:35