Übergeben von Befehlszeilenargumenten an R CMD BATCH

102

Ich habe R CMD BATCH my_script.Rvon einem Terminal aus ein RSkript ausgeführt. Ich bin jetzt an dem Punkt angelangt, an dem ich dem Befehl ein Argument übergeben möchte, habe aber einige Probleme, damit es funktioniert. Wenn ich das tue , R CMD BATCH my_script.R blabladann blablawird die Ausgabedatei, anstatt zur Verfügung Skript die R als Argument interpretiert wird ausgeführt werden.

Ich habe versucht, Rscript my_script.R blablawas blablaals Argument richtig weiterzugeben scheint , aber dann bekomme ich nicht die my_script.RoutAusgabedatei, mit der ich komme R CMD BATCH(ich möchte die .RoutDatei). Während ich die Ausgabe eines Aufrufs an Rscripteinen Dateinamen meiner Wahl umleiten könnte , würde ich die in der Datei enthaltenen R-Eingabebefehle nicht R CMD BATCHwie in der .RoutDatei erhalten.

Im Idealfall bin ich also auf der Suche nach einer Möglichkeit, Argumente an ein R-Skript zu übergeben, das über die R CMD BATCHMethode ausgeführt wird. Ich würde mich jedoch über einen Ansatz freuen, der verwendet wird, Rscriptwenn es eine Möglichkeit gibt, eine vergleichbare .RoutDatei zu erstellen.

Bryce Thomas
quelle

Antworten:

112

Mein Eindruck ist, dass das R CMD BATCHein Relikt ist. In jedem Fall macht die neuere Rscriptausführbare Datei (auf allen Plattformen verfügbar) zusammen mit commandArgs()der Verarbeitung von Befehlszeilenargumenten ziemlich einfach.

Als Beispiel hier ein kleines Skript - nennen Sie es "myScript.R":

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

Und so sieht es aus, wenn Sie es über die Befehlszeile aufrufen

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

Bearbeiten:

Nicht, dass ich es empfehlen würde, aber ... mit einer Kombination von source()und sink()könnten Sie Rscripteine .RoutDatei wie die von erstellen R CMD BATCH. Eine Möglichkeit wäre, ein kleines R-Skript zu erstellen - nennen Sie es RscriptEcho.R - das Sie direkt mit Rscript aufrufen. Es könnte so aussehen:

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

Um Ihr eigentliches Skript auszuführen, würden Sie dann Folgendes tun:

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

Dies wird myScript.Rmit den angegebenen Argumenten ausgeführt und verschachtelte Eingaben, Ausgaben und Nachrichten an einen eindeutigen Namen senden .Rout.

Edit2:
Sie können Rscript ausführlich ausführen und die ausführliche Ausgabe in eine Datei einfügen.

Rscript --verbose myScript.R 5 100 > myScript.Rout
Josh O'Brien
quelle
4
Ich habe auch den Eindruck, R CMD BATCHein Relikt zu sein. Das, was mir daran gefällt, ist, dass es eine .RoutDatei erzeugt , die nicht nur die Skriptausgabe enthält, sondern auch die Eingabebefehle / Kommentare aus der .RSkriptdatei verschachtelt , die diese Ausgabe erzeugt hat.
Bryce Thomas
1
Ich höre dich. Das war (ich denke immer noch!) Ein schöner Aspekt von R CMD BATCH.
Josh O'Brien
5
aber ich denke , man kann es besser machen als R CMD BATCHmit knitr, zum Beispiel Rscript -e "knitr::stitch(commandArgs(TRUE)[1])" my_script.R(können Sie ersetzen stitchmit stitch_rhtmloder stitch_rmd, und Sie müssen installieren knitrvon Github , da ich nur einen Fehler gefunden stitch...)
Yihui Xie
7
Nur um meine 0.02 hinzuzufügen, ist es auch einfach, die Umleitung vom Terminal zu verwenden. Ein Beispiel ist, Rscript myfile.R > path/to/mylog.Routund anstatt auf stdout (dem Bildschirm) gedruckt zu werden, wird die Ausgabe der Datei in Ihrer .RoutDatei gespeichert.
James Pringle
3
Um @JamesPringle hinzuzufügen, möchte ich häufig, dass meine Ausgabe sowohl auf einem Bildschirm (zur Überwachung in Echtzeit) als auch in einer Datei (zur späteren Ansicht) gedruckt wird. Ich tueRscript myfile.R | tee mylog.Rout
Heisenberg
26

Nachdem ich die hier beschriebenen Optionen ausprobiert hatte, fand ich diesen Beitrag von Forester in R-Bloggern. Ich denke, es ist eine saubere Option.

Ich habe seinen Code hier eingefügt:

Von der Kommandozeile

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

In test.out

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

Danke an Forester !

Alex A.
quelle
Es ist wichtig zu beachten, dass bei Argumenten vom Typ Zeichen keine einfachen / doppelten Anführungszeichen verwendet werden müssen. Beispiel: R CMD BATCH '--args a = FolderName' test.R test.out &
d2a2d
Wie in Foresters Beitrag erwähnt, --argsist der Schlüssel. Es funktioniert auch mit R --no-save --no-restore --args a=1 < test.RundR --no-save --no-restore < test.R --args a=1
Dave
Gibt es eine Möglichkeit, Argumente von der Befehlszeile an die --args zu übergeben? Angenommen, wir möchten eine for-Schleife in der Befehlszeile ausführen und sie dann in der Zeile --args senden.
user2809432
9

In Ihrem R-Skript heißt es test.R:

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

Führen Sie über die Befehlszeile Folgendes aus:

R CMD BATCH -4 test.R

Ihre Ausgabedatei test.Rout zeigt an, dass das Argument 4erfolgreich an R übergeben wurde:

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 
user1563570
quelle
8

Sie müssen Argumente vor setzen my_script.Rund -für die Argumente verwenden, z

R CMD BATCH -blabla my_script.R

commandArgs()wird -blablain diesem Fall als Zeichenkette empfangen . Weitere Informationen finden Sie in der Hilfe:

$ 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.
Yihui Xie
quelle
2
Ich merke , wenn ich es auf diese Weise und im Skript verwenden zu tun args <- commandArgs(FALSE)und dann args drucken, ich mit allen Argumenten am Ende, auch solche, die nicht von mir sind, wie --restore, --saveetc. Wenn ich commandArgs(TRUE)mich keine Argumente überhaupt bekommen. Gibt es eine Möglichkeit, nur meine eigenen zusätzlichen Argumente zu erhalten? --argssieht vielversprechend aus, aber ich habe es nicht zum Laufen gebracht ...
Bryce Thomas
Sie müssen die Argumente vom Ende zählen (z. B. Größe 2, Größe 1, Größe) - Ihre werden immer am Ende sein.
Ynka
4

Ich füge eine Antwort hinzu, weil ich denke, dass eine einzeilige Lösung immer gut ist! Fügen Sie über Ihrer myRscript.RDatei die folgende Zeile hinzu:

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

Dann senden Sie Ihr Skript mit etwas wie:

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

Beispielsweise:

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

Dann:

> ls()
[1] "N"    "l"    "name"
ClementWalter
quelle
0

Hier ist eine andere Möglichkeit, Befehlszeilenargumente mit zu verarbeiten R CMD BATCH. Mit meinem Ansatz, der auf einer früheren Antwort hier aufbaut , können Sie Argumente in der Befehlszeile angeben und in Ihrem R-Skript einige oder alle Standardwerte angeben.

Hier ist eine R-Datei, die ich test.R nenne :

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)

In der Kommandozeile, wenn ich tippe

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

dann haben wir innerhalb von R a= 2und b= c(2,5,6). Aber ich könnte zum Beispiel weglassen bund ein anderes Argument hinzufügen c:

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

Dann haben wir in R a= 2, b= c(1,1,1)(die Standardeinstellung) und c= "hello".

Schließlich können wir der Einfachheit halber den R-Code in eine Funktion einbinden, solange wir uns um die Umgebung kümmern:

## 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)))
Dagremu
quelle