111 votes

Passage d'arguments de ligne de commande à R CMD BATCH

J'ai utilisé R CMD BATCH my_script.R à partir d'un terminal pour exécuter un R script. Je suis maintenant au point où je voudrais passer un argument à la commande, mais j'ai quelques problèmes pour le faire fonctionner. Si je fais R CMD BATCH my_script.R blabla puis 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 passer sur blabla correctement comme un argument, mais alors je ne comprends pas la my_script.Rout que j'obtiens avec R CMD BATCH (Je veux le .Rout fichier). Alors que je pourrais rediriger la sortie d'un appel à Rscript à un nom de fichier de mon choix, je n'obtiendrais pas les commandes d'entrée R incluses dans le fichier de la manière dont R CMD BATCH fait dans le .Rout fichier.

Donc, idéalement, je cherche un moyen de passer des arguments à un script R exécuté par l'intermédiaire de l'interface de l'utilisateur. R CMD BATCH mais je serais satisfait d'une approche utilisant la méthode de la Rscript s'il y a un moyen de lui faire produire un résultat comparable. .Rout fichier.

123voto

Josh O'Brien Points 68397

J'ai l'impression que R CMD BATCH est un peu une relique. En tout cas, les plus récents Rscript (disponible sur toutes les plates-formes), ainsi que l'application commandArgs() rend le traitement des arguments de ligne de commande assez facile.

A titre d'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 son invocation à partir de la ligne de commande

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

Edit :

Non pas que je le recommande, mais ... en utilisant une combinaison de source() y sink() vous pourriez obtenir Rscript pour produire un .Rout comme celui produit par R CMD BATCH . Une façon de faire serait de créer un petit script R -- appeler il RscriptEcho.R -- que vous appelez directement avec Rscript. Ça pourrait ressembler à ça :

## 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 réel, 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 envoie l'entrée, la sortie et les messages entrelacés vers un fichier nommé de façon unique .Rout .

Edit2 :
Vous pouvez exécuter Rscript de manière verbeuse et placer la sortie verbeuse dans un fichier.

Rscript --verbose myScript.R 5 100 > myScript.Rout

7 votes

J'ai aussi l'impression R CMD BATCH est une relique. Ce que j'aime bien, c'est qu'il produit une .Rout qui n'inclut pas seulement la sortie du script, mais qui entrelace également les commandes/commentaires d'entrée de l'application .R script qui a produit cette sortie.

1 votes

Je vous entends. C'était (je suppose que c'est toujours le cas !) un aspect agréable de R CMD BATCH .

5 votes

Mais je pense que vous pouvez faire mieux que R CMD BATCH con knitr par exemple Rscript -e "knitr::stitch(commandArgs(TRUE)[1])" my_script.R (vous pouvez remplacer stitch con stitch_rhtml o stitch_rmd et vous devez installer knitr de Github puisque je viens de trouver un bug dans stitch ...)

29voto

Alex A. Points 73

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

J'ai mis 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 !

0 votes

Il est important de noter que si les arguments sont de type caractère, il n'est pas nécessaire d'utiliser des guillemets simples/doubles. Par exemple R CMD BATCH '--args a=FolderName' test.R test.out &

0 votes

Comme mentionné dans le post de Forester, --args est la clé. Cela fonctionne aussi avec R --no-save --no-restore --args a=1 < test.R y R --no-save --no-restore < test.R --args a=1

0 votes

Y a-t-il un moyen de passer des arguments de la ligne de commande dans le --args ? Disons que nous voulons faire une boucle for dans la ligne de commande, puis l'envoyer dans la ligne --args.

11voto

Yihui Points 9906

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

R CMD BATCH -blabla my_script.R

commandArgs() recevront -blabla comme une chaîne de caractères dans ce cas. Consultez 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.

2 votes

Je remarque que si je le fais de cette manière et que dans le script j'utilise args <- commandArgs(FALSE) et ensuite imprimer args, je me retrouve avec tous les arguments, y compris ceux qui ne sont pas les miens, comme --restore , --save etc. Si j'utilise commandArgs(TRUE) Je ne reçois aucun argument. Existe-t-il un moyen d'obtenir uniquement mes propres arguments supplémentaires ? --args semble prometteur, mais je n'ai pas réussi à le faire fonctionner...

0 votes

Vous devez compter les arguments à partir de la fin (par exemple, taille-2, taille-1, taille) - le vôtre sera toujours à la fin.

9voto

user1563570 Points 56

Dans votre script R, appelé test.R :

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

Depuis la ligne de commande, exécutez :

R CMD BATCH -4 test.R

Votre fichier de sortie, test.Rout, montrera que l'argument 4 a été transmis 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

4voto

clemlaflemme Points 1566

J'ajoute une réponse parce que je pense qu'une solution en une ligne est toujours bonne ! En haut de votre 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"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X