2011-10-19 24 views
92

estoy un poco confundido acerca de la instrucción switch en R. simplemente buscando en Google la función consigo un ejemplo de la siguiente manera:interruptor() uso de sentencias

Un uso común del interruptor está en rama en función del valor del carácter uno de los argumentos para una función.

> 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 

Sin embargo, esto sólo parece ser el mismo que acaba de tener un montón de if declaraciones designado para cada type

¿Eso es todo lo que hay que switch()? ¿Puede alguien darme más ejemplos y mejores aplicaciones?

+7

Sí, eso es todo. – Andrie

Respuesta

95

Bueno, el tiempo para el rescate de nuevo. Parece que switch es generalmente más rápido que las declaraciones if. Para que , y el hecho de que el código es más corto/más limpio con una declaración switch se inclina a favor de 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 

actualización con el comentario de Joshua en mente, he intentado otras formas de determinar. El microbenchmark parece ser el mejor. ... y se nota tiempos similares:

> 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 

actualización final Aquí está mostrando la versatilidad switch es:

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

Este case2 mapas y case3 a 2.5 y el valor por defecto (sin nombre) a 99. Para obtener más información, intente ?switch

+2

El uso de un bucle for como este puede causar problemas con la recolección de basura. La diferencia es mucho menor con una mejor función de benchmarking: 'benchmark (test1 ('trimmed'), test2 ('trimmed'), replications = 1e6)'. –

+0

@JoshuaUlrich ... ¿qué función de 'punto de referencia' estás usando? No es el obvio del paquete de "referencia" parece? – Tommy

+1

Disculpa, estaba usando el paquete rbenchmark. –

2

En resumen, . Pero hay momentos en los que puedes favorecer a uno contra el otro. Google "cambio de caso vs. if else". También hay discusiones sobre SO. Además, aquí es un buen video que habla de ello en el contexto de MATLAB:

http://blogs.mathworks.com/pick/2008/01/02/matlab-basics-switch-case-vs-if-elseif/

Personalmente, cuando tenga 3 o más casos, por lo general sólo tiene que ir con el caso/interruptor.