utilizzo dell'istruzione switch ()


106

Sono un po 'confuso riguardo all'istruzione switch in R. Semplicemente cercando su Google la funzione ottengo un esempio come segue:

Un uso comune di switch consiste nel diramare in base al valore del carattere di uno degli argomenti di una funzione.

 > centre <- function(x, type) {
 + switch(type,
 +        mean = mean(x),
 +        median = median(x),
 +        trimmed = mean(x, trim = .1))
 + }
 > x <- rcauchy(10)
 > centre(x, "mean")
 [1] 0.8760325
 > centre(x, "median")
 [1] 0.5360891
 > centre(x, "trimmed")
 [1] 0.6086504

Tuttavia questo sembra essere lo stesso che avere un mucchio di ifdichiarazioni designate per ciascunatype

È tutto quello che c'è da fare switch()? Qualcuno può fornirmi ulteriori esempi e applicazioni migliori?


10
Sì, è tutto quello che c'è da fare.
Andrie

Risposte:


119

Bene, tempismo per il salvataggio di nuovo. Sembra che switchsia generalmente più veloce delle ifdichiarazioni. Quindi, e il fatto che il codice sia più breve / più ordinato con switchun'istruzione si appoggia a favore di switch:

# Simplified to only measure the overhead of switch vs if

test1 <- function(type) {
 switch(type,
        mean = 1,
        median = 2,
        trimmed = 3)
}

test2 <- function(type) {
 if (type == "mean") 1
 else if (type == "median") 2
 else if (type == "trimmed") 3
}

system.time( for(i in 1:1e6) test1('mean') ) # 0.89 secs
system.time( for(i in 1:1e6) test2('mean') ) # 1.13 secs
system.time( for(i in 1:1e6) test1('trimmed') ) # 0.89 secs
system.time( for(i in 1:1e6) test2('trimmed') ) # 2.28 secs

Aggiornamento Tenendo presente il commento di Joshua, ho provato altri modi per eseguire il benchmark. Il microbenchmark sembra il migliore. ... e mostra tempi simili:

> library(microbenchmark)
> microbenchmark(test1('mean'), test2('mean'), times=1e6)
Unit: nanoseconds
           expr  min   lq median   uq      max
1 test1("mean")  709  771    864  951 16122411
2 test2("mean") 1007 1073   1147 1223  8012202

> microbenchmark(test1('trimmed'), test2('trimmed'), times=1e6)
Unit: nanoseconds
              expr  min   lq median   uq      max
1 test1("trimmed")  733  792    843  944 60440833
2 test2("trimmed") 2022 2133   2203 2309 60814430

Aggiornamento finale Ecco che mostra quanto sia versatile switch:

switch(type, case1=1, case2=, case3=2.5, 99)

Questo mappa case2e case3a 2.5e il valore predefinito (senza nome) su 99. Per ulteriori informazioni, prova?switch


3
L'uso di un ciclo for come quello può causare problemi con la garbage collection. La differenza è molto più piccolo con una migliore funzione di benchmarking: benchmark(test1('trimmed'), test2('trimmed'), replications=1e6).
Joshua Ulrich

@JoshuaUlrich ... quale benchmarkfunzione stai usando? Non quello ovvio dal pacchetto "benchmark", sembra?
Tommy

1
Secondo stackoverflow.com/questions/6262203/… "microbenchmark" è ancora migliore.
Tommy

@JoshuaUlrich - Ho aggiornato la risposta con i risultati di microbencmark, ma sono molto simili a quelli originali. Non vedo davvero come rbenchmark potrebbe aggirare il problema GC, ma sembra che abbia più overhead chiamando evale replicate.
Tommy

così come sono a parte posso avere più casi con lo stesso output? vale a direswitch(type, c(this,that)=do something)
LostLin

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.