2010-01-27 27 views
257

Tengo un script R para el cual me gustaría poder proporcionar varios parámetros de línea de comandos (en lugar de valores de parámetro de código duro en el código). La secuencia de comandos se ejecuta en Windows.¿Cómo puedo leer los parámetros de línea de comandos desde un script R?

No encuentro información sobre cómo leer los parámetros proporcionados 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 de Google ...

¿Alguna sugerencia o recomendación?

+0

necesita configurar la ubicación del ejecutable rscript –

Respuesta

189

Dirk's answer here es todo lo que necesita. 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 que obtendrá:

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

También puede añadir una variable de entorno %R_Script%:

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

y Úselo en sus secuencias de comandos por lotes como %R_Script% <filename.r> <arguments>

Las diferencias entre RScript y Rterm:

  • Rscript tiene una sintaxis más simple
  • Rscript elige automáticamente la arquitectura de 64 bits (ver R Installation and Administration, 2.6 Sub-architectures para más detalles)
  • Rscript necesidades options(echo=TRUE) en el archivo .R si desea escribir la comandos al archivo de salida
8

necesita littler (pronunciado 'poco r')

Dirk será por unos 15 minutos para elaborar;)

+23

Llegué con siete minutos de retraso. Debe haber sido un mal tráfico en los Intertubes. –

+2

ya sea eso o estás envejeciendo. ;) –

+2

Claramente, no leí bien su pregunta. -1 para mí al no poder ver el requisito de Windows –

114

Unos pocos puntos:

  1. parámetros de línea de comandos son accesible a través de commandArgs(), por lo que ver help(commandArgs) para obtener una descripción general de .

  2. Puede usar Rscript.exe en todas las plataformas, incluido Windows. Será compatible con commandArgs(). littler podría ser portado a Windows, pero vive en este momento solo en OS X y Linux.

  3. Hay dos paquetes complementarios en CRAN - getopt y optparse - que fueron escritos para el análisis de línea de comandos.

Editar en noviembre de 2015: Nuevas alternativas han aparecido y yo de todo corazón recomendar doctopt.

+8

+1 para el puntero al paquete 'optparse'. – reprogrammer

+2

y hay [argparse] (http://cran.r-project.org/web/packages/argparse/index.html) – gkcn

79

Agregue esto al principio de su script:

args<-commandArgs(TRUE) 

A continuación, se puede hacer referencia a los argumentos que se pasan como args[1], etc. args[2]

A continuación, ejecute

Rscript myscript.R arg1 arg2 arg3 

Si sus argumentos son cadenas con espacios en ellos, encierran entre comillas dobles.

+7

Esto solo funcionó cuando usé args <-commandArgs (TRUE) (tenga en cuenta la letra A mayúscula) . –

+0

¿necesitas --args antes de arg1? – philcolbourn

+0

@philcolbourn No –

4

En bash, puede construir una línea de comando como el 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 
$ 

Se puede ver que la variable $z está sustituido con cáscara del golpe con el "10" y este valor es recogido por commandArgs y alimentado en args[2], y el alcance de mando x=1:10 ejecutado por R con éxito, etc etc.

3

FYI: hay una función args(), que recupera los argumentos de funciones R, que no debe confundirse con un vector de argumentos con nombre args

+1

Esto es casi seguro que no es el caso. Solo las funciones pueden enmascarar funciones. Crear una variable con el mismo nombre como una función no enmascara la función. Consulte esta pregunta y sus respuestas: http://stackoverflow.com/q/6135868/602276 – Andrie

+0

Cierto, no lo enmascara. En general, trato de evitar nombrar funciones y variables con nombres que ya existen en R. – Tim

12

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(); 
} 
0

Acabo de armar una buena estructura de datos y una cadena de procesamiento para generar este comportamiento de conmutación, no se necesitan bibliotecas. Estoy seguro de que habrá sido implementado muchas veces, y encontré este hilo buscando ejemplos, pensé que lo haría.

Ni siquiera necesitaba banderas en particular (el único indicador aquí es un modo de depuración, creando una variable que verifico como una condición para iniciar una función en sentido descendente if (!exists(debug.mode)) {...} else {print(variables)}). La siguiente marca de verificación lapply produce lo mismo que:

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

donde args es la variable de lectura desde los argumentos de línea de comandos (un vector de caracteres, lo que equivale a c('--debug','--help') al proporcionar estos en, por ejemplo)

es reutilizable para cualquier otra bandera y evitar toda la repetición y no hay bibliotecas así 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)) 

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

muestra:

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

-h --help Display flag definitions
6

Desde optparse se ha mencionado un par de veces en las respuestas, y proporciona un kit completo para el procesamiento de línea de comandos, aquí hay un pequeño ejemplo simplificado de cómo se puede usar, suponiendo que el archivo de entrada existe:

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

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

En la línea de comandos:

Rscript script.R -hsalidas

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

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

Cuestiones relacionadas