web-dev-qa-db-fra.com

Passer des arguments de ligne de commande à R CMD BATCH

J'utilise R CMD BATCH my_script.R depuis un terminal pour exécuter un script R. Je suis maintenant sur le point de passer un argument à la commande, mais j'ai du mal à le faire fonctionner. Si je fais R CMD BATCH my_script.R blabla, alors blabla devient le fichier de sortie, plutôt que d'être interprété comme un argument disponible pour le script R en cours d'exécution.

J'ai essayé Rscript my_script.R blabla qui semble transmettre correctement l'argument blabla, mais je ne reçois pas le fichier de sortie my_script.Rout que je reçois avec R CMD BATCH (je veux le fichier .Rout). Bien que je puisse rediriger la sortie d'un appel vers Rscript vers un nom de fichier de mon choix, je ne recevrais pas les commandes d'entrée R incluses dans le fichier de la même manière que R CMD BATCH dans le fichier .Rout

Donc, idéalement, je recherche un moyen de passer des arguments à un script R exécuté via la méthode R CMD BATCH, mais serait heureux d’une approche utilisant Rscript s’il est possible de le faire produire un fichier .Rout comparable.

87
Bryce Thomas

Mon impression est que R CMD BATCH est un peu un relict. Dans tous les cas, l'exécutable Rscript plus récent (disponible sur toutes les plates-formes), associé à commandArgs(), facilite le traitement des arguments de ligne de commande.

Par exemple, voici un petit script - appelez-le "myScript.R":

## myScript.R
args <- commandArgs(trailingOnly = TRUE)
rnorm(n=as.numeric(args[1]), mean=as.numeric(args[2]))

Et voici à quoi ressemble l'invocation depuis la ligne de commande

> Rscript myScript.R 5 100
[1]  98.46435 100.04626  99.44937  98.52910 100.78853

Modifier:

Non pas que je le recommande, mais ... en combinant les fonctions source() et sink(), vous pouvez obtenir Rscript pour générer un fichier .Rout similaire à celui produit par R CMD BATCH. Une solution serait de créer un petit script R - appelez le RscriptEcho.R - que vous appelez directement avec Rscript. Cela pourrait ressembler à ceci:

## RscriptEcho.R
args <- commandArgs(TRUE)
srcFile <- args[1]
outFile <- paste0(make.names(date()), ".Rout")
args <- args[-1]

sink(outFile, split = TRUE)
source(srcFile, echo = TRUE)

Pour exécuter votre script actuel, vous feriez alors:

Rscript RscriptEcho.R myScript.R 5 100
[1]  98.46435 100.04626  99.44937  98.52910 100.78853

qui exécutera myScript.R avec les arguments fournis et absorbera les entrées, les sorties et les messages entrelacés dans un .Rout unique.

Edit2:
Vous pouvez exécuter Rscript verbalement et placer la sortie détaillée dans un fichier.

Rscript --verbose myScript.R 5 100 > myScript.Rout
93
Josh O'Brien

Après avoir essayé les options décrites ici, j’ai trouvé ce message de Forester dans r-bloggers. Je pense que c'est une option propre à considérer. 

Je mets son code ici:

Depuis la ligne de commande

$ R CMD BATCH --no-save --no-restore '--args a=1 b=c(2,5,6)' test.R test.out &

Test.R

##First read in the arguments listed at the command line
args=(commandArgs(TRUE))

##args is now a list of character vectors
## First check to see if arguments are passed.
## Then cycle through each element of the list and evaluate the expressions.
if(length(args)==0){
    print("No arguments supplied.")
    ##supply default values
    a = 1
    b = c(1,1,1)
}else{
    for(i in 1:length(args)){
      eval(parse(text=args[[i]]))
    }
}

print(a*2)
print(b*3)

Dans test.out

> print(a*2)
[1] 2
> print(b*3)
[1]  6 15 18

Merci à Forester !

22
Alex A.

Dans votre script R, appelé test.R:

args <- commandArgs(trailingOnly = F)
myargument <- args[length(args)]
myargument <- sub("-","",myargument)
print(myargument)
q(save="no")

A partir de la ligne de commande, lancez:

R CMD BATCH -4 test.R

Votre fichier de sortie, test.Rout, montrera que l'argument 4 a été passé avec succès à R:

cat test.Rout

> args <- commandArgs(trailingOnly = F)
> myargument <- args[length(args)]
> myargument <- sub("-","",myargument)
> print(myargument)
[1] "4"
> q(save="no")
> proc.time()
user  system elapsed 
0.222   0.022   0.236 
9
user1563570

Vous devez placer les arguments avant my_script.R et utiliser - sur les arguments, par exemple.

R CMD BATCH -blabla my_script.R

commandArgs() recevra -blabla sous forme de chaîne de caractères dans ce cas. Voir l'aide pour plus de détails:

$ R CMD BATCH --help
Usage: R CMD BATCH [options] infile [outfile]

Run R non-interactively with input from infile and place output (stdout
and stderr) to another file.  If not given, the name of the output file
is the one of the input file, with a possible '.R' extension stripped,
and '.Rout' appended.

Options:
  -h, --help        print short help message and exit
  -v, --version     print version info and exit
  --no-timing           do not report the timings
  --            end processing of options

Further arguments starting with a '-' are considered as options as long
as '--' was not encountered, and are passed on to the R process, which
by default is started with '--restore --save --no-readline'.
See also help('BATCH') inside R.
8
Yihui Xie

J'ajoute une réponse car je pense qu'une solution d'une ligne est toujours bonne! Au sommet de votre fichier myRscript.R, ajoutez la ligne suivante:

eval(parse(text=paste(commandArgs(trailingOnly = TRUE), collapse=";")))

Puis soumettez votre script avec quelque chose comme:

R CMD BATCH [options] '--args arguments you want to supply' myRscript.R &

Par exemple:

R CMD BATCH --Vanilla '--args N=1 l=list(a=2, b="test") name="aname"' myscript.R &

Ensuite:

> ls()
[1] "N"    "l"    "name"
3
clemlaflemme

Voici un autre moyen de traiter les arguments de ligne de commande, en utilisant R CMD BATCH. Mon approche, qui repose sur une réponse antérieure ici , vous permet de spécifier des arguments sur la ligne de commande et, dans votre script R, de donner à tout ou partie de leurs valeurs par défaut.

Voici un fichier R, que je nomme test.R:

defaults <- list(a=1, b=c(1,1,1)) ## default values of any arguments we might pass

## parse each command arg, loading it into global environment
for (arg in commandArgs(TRUE))
  eval(parse(text=arg))

## if any variable named in defaults doesn't exist, then create it
## with value from defaults
for (nm in names(defaults))
  assign(nm, mget(nm, ifnotfound=list(defaults[[nm]]))[[1]])

print(a)
print(b)

Sur la ligne de commande, si je tape

R CMD BATCH --no-save --no-restore '--args a=2 b=c(2,5,6)' test.R

alors dans R nous aurons a = 2 et b = c(2,5,6). Mais je pourrais, par exemple, omettre b et ajouter un autre argument c:

R CMD BATCH --no-save --no-restore '--args a=2 c="hello"' test.R

Ensuite, dans R, nous aurons a = 2, b = c(1,1,1) (valeur par défaut) et c = "hello".

Enfin, pour plus de commodité, nous pouvons inclure le code R dans une fonction, à condition de respecter l'environnement:

## defaults should be either NULL or a named list
parseCommandArgs <- function(defaults=NULL, envir=globalenv()) {
  for (arg in commandArgs(TRUE))
    eval(parse(text=arg), envir=envir)

  for (nm in names(defaults))
    assign(nm, mget(nm, ifnotfound=list(defaults[[nm]]), envir=envir)[[1]], pos=envir)
}

## example usage:
parseCommandArgs(list(a=1, b=c(1,1,1)))
0
Dagremu