2010-01-27 13 views
257

Mam skrypt R, dla którego chciałbym być w stanie dostarczyć kilka parametrów wiersza polecenia (zamiast wartości parametrów kodowania w samym kodzie). Skrypt działa w systemie Windows.Jak mogę odczytać parametry wiersza poleceń ze skryptu R?

Nie mogę znaleźć informacji o tym, jak odczytywać parametry podane w wierszu poleceń do mojego skryptu R. Byłbym zaskoczony, gdyby nie można było tego zrobić, więc może po prostu nie używam najlepszych słów kluczowych w mojej wyszukiwarce Google ...

Jakieś wskazówki czy rekomendacje?

+0

musisz ustawić lokalizację wykonywalnego pliku rscript –

Odpowiedz

189

Dirk's answer here to wszystko, czego potrzebujesz. Oto minimalny powtarzalny przykład. Utworzono dwa pliki: exmpl.bat i 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 
    

    Alternatywnie, przy użyciu 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) 
    

Zapisz oba pliki w tym samym katalogu i uruchom exmpl.bat.W rezultacie otrzymasz:

  • example.png z jakimś spisku
  • exmpl.batch ze wszystkim, co zostało zrobione

Można także dodać zmienną środowiskową %R_Script%:

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

i użyj go w swoich skryptach wsadowych jako %R_Script% <filename.r> <arguments>

Różnice między RScript i Rterm:

8

trzeba littler (wymawiane 'trochę R')

Dirk będzie przez około 15 minut, aby opracować;)

+23

Spóźniłem się siedem minut. Musiał to być zły ruch na Intertubach. –

+2

albo to, albo się starzejesz. ;) –

+2

Ja wyraźnie nie czytałem jego pytania dobrze. -1 dla mnie nie widzę wymagania Windows –

114

Kilka punktów:

  1. parametry wiersza polecenia są dostępne przez commandArgs(), czyli , zobacz help(commandArgs), aby uzyskać przegląd ogólny.

  2. Możesz używać Rscript.exe na wszystkich platformach, w tym Windows. Będzie wspierać commandArgs(). littler może być przeniesiony do systemu Windows, ale działa teraz tylko w systemie OS X i Linux.

  3. Istnieją dwa pakiety dodatkowe na CRAN - getopt i optparse - które zostały napisane dla parsowania w linii poleceń.

Edycja w listopadzie 2015: Nowe alternatywy pojawiły się całym sercem i mam polecić doctopt.

+8

+1 dla wskaźnika do pakietu 'optparse'. – reprogrammer

+2

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

79

Dodaj to do początku skryptu:

args<-commandArgs(TRUE) 

Następnie można odnieść się do argumentów przekazanych jako args[1], args[2] itp

Następnie uruchom

Rscript myscript.R arg1 arg2 arg3 

Jeśli twoje argumenty są ciągami znaków ze spacjami w nich dołączyć wewnątrz cudzysłowów.

+7

To działało tylko wtedy, gdy użyłem args <-commandArgs (TRUE) (zauważ wielkie litery A) . –

+0

potrzebujesz --args przed arg1? – philcolbourn

+0

@philcolbourn No –

4

W bash, można skonstruować wiersz polecenia jak poniżej:

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

Można zobaczyć, że zmienna $z jest podstawiona przez powłoki bash z „10” i wartość ta zostanie odebrany przez commandArgs i Fed w args[2], a zakres polecenia x=1:10 wykonywane przez R powodzeniem itd itp

3

FYI: jest argumentów funkcji(), która pobiera argumentów funkcji R, nie mogą być mylone z wektorem argumentów wymienionych args

+1

To prawie na pewno nie dotyczy. Tylko funkcje mogą maskować funkcje. Utworzenie zmiennej o tej samej nazwie jak funkcja nie maskuje tej funkcji. Zobacz to pytanie i odpowiedzi: http://stackoverflow.com/q/6135868/602276 – Andrie

+0

To prawda, nie maskuje go. Ogólnie rzecz biorąc, staram się unikać nazewnictwa funkcji i zmiennych o nazwach, które już istnieją w R. – Tim

12

Spróbuj biblioteki (getopt) ... jeśli chcesz, aby wszystko było ładniejsze. Na przykład:

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

Właśnie stworzyłem ładną strukturę danych i łańcuch przetwarzania w celu wygenerowania tego zachowania przełączania, bez potrzebnych bibliotek. Jestem pewien, że zostanie on zaimplementowany wiele razy, i natknął się na ten wątek szukając przykładów - myślałem, że będę chipować.

Nie potrzebowałem nawet flag (jedyną flagą jest tutaj tryb debugowania, tworząc zmienną, którą sprawdzam jako warunek uruchomienia funkcji downstream if (!exists(debug.mode)) {...} else {print(variables)}). Poniższe instrukcje sprawdzania bandery dają następujące wyniki:

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

gdzie args jest zmienną odczytać z argumentów wiersza poleceń (wektor znaków, co odpowiada c('--debug','--help') gdy podasz je na przykład)

jest wielokrotnego użytku dla innych flagi i uniknąć wszystkich powtórzeń , i Brak biblioteki, więc nie ma zależności:

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

pamiętać, że w flag.details tutaj polecenia są przechowywane jako ciągi, a następnie oceniano przy eval(parse(text = '...')). Optparse jest oczywiście pożądany dla każdego poważnego skryptu, ale kod minimalnej funkcjonalności też jest czasem dobry. Wyjście

Próbka:

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

-h --help Display flag definitions
6

Od optparse już wspomniano kilka razy w odpowiedziach i zapewnia kompleksowy zestaw do przetwarzania wiersza poleceń, oto krótki uproszczony przykład tego, jak można go używać, przy założeniu, że istnieje plik wejściowy:

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

Podano arbitralny plik blah.txt z 23 liniami.

na linii polecenia:

Rscript script.R -hwyjścia

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.txtwyjścia[1] "69"

Rscript script.R -n -f 5 blah.txtwyjścia[1] "115"

Powiązane problemy