¿Cómo usar la instrucción switch en funciones R?

81

Me gustaría usar para mi función en R la declaración switch()para desencadenar cálculos diferentes de acuerdo con el valor del argumento de la función.

Por ejemplo, en Matlab puede hacerlo escribiendo

switch(AA)        
case '1'   
...   
case '2'   
...   
case '3'  
...  
end

Encontré este uso de la declaración post - switch () , que explica cómo usarlo switch, pero no es realmente útil para mí, ya que quiero realizar cálculos más sofisticados (operaciones matriciales) y no un simple mean.

Simón
fuente

Respuestas:

112

Bueno, switchprobablemente no estaba realmente destinado a funcionar así, pero puedes:

AA = 'foo'
switch(AA, 
foo={
  # case 'foo' here...
  print('foo')
},
bar={
  # case 'bar' here...
  print('bar')    
},
{
   print('default')
}
)

... cada caso es una expresión, generalmente una cosa simple, pero aquí uso un bloque rizado para que pueda introducir el código que desee allí ...

Tommy
fuente
6
¿Hay alguna manera de hacer esto sin comparar con cadenas? eso parece muy ineficiente.
Jules GM
10
Como nuevo usuario de switch(), me pregunto por qué dice que no está destinado a funcionar así. ¿Qué más esperaría que hiciera una declaración de cambio?
eric_kernfeld
46

esas diversas formas de cambiar ...

# by index
switch(1, "one", "two")
## [1] "one"


# by index with complex expressions
switch(2, {"one"}, {"two"})
## [1] "two"


# by index with complex named expression
switch(1, foo={"one"}, bar={"two"})
## [1] "one"


# by name with complex named expression
switch("bar", foo={"one"}, bar={"two"})
## [1] "two"
Petermeissner
fuente
42

Espero que este ejemplo ayude. Puede usar las llaves para asegurarse de que tiene todo incluido en el tipo del cambiador de conmutador (lo siento, no conozco el término técnico, pero el término que precede al signo = cambia lo que sucede). Pienso en Switch como un grupo de if () {} else {}declaraciones más controladas .

Cada vez que la función del interruptor es la misma, pero el comando que proporcionamos cambia.

do.this <- "T1"

switch(do.this,
    T1={X <- t(mtcars)
        colSums(mtcars)%*%X
    },
    T2={X <- colMeans(mtcars)
        outer(X, X)
    },
    stop("Enter something that switches me!")
)
#########################################################
do.this <- "T2"

switch(do.this,
    T1={X <- t(mtcars)
        colSums(mtcars)%*%X
    },
    T2={X <- colMeans(mtcars)
        outer(X, X)
    },
    stop("Enter something that switches me!")
)
########################################################
do.this <- "T3"

switch(do.this,
    T1={X <- t(mtcars)
        colSums(mtcars)%*%X
    },
    T2={X <- colMeans(mtcars)
        outer(X, X)
    },
    stop("Enter something that switches me!")
)

Aquí está dentro de una función:

FUN <- function(df, do.this){
    switch(do.this,
        T1={X <- t(df)
            P <- colSums(df)%*%X
        },
        T2={X <- colMeans(df)
            P <- outer(X, X)
        },
        stop("Enter something that switches me!")
    )
    return(P)
}

FUN(mtcars, "T1")
FUN(mtcars, "T2")
FUN(mtcars, "T3")
Tyler Rinker
fuente
0

Esta es una respuesta más general a la construcción faltante "Select cond1, stmt1, ... else stmtelse" en R. Es un poco gaseosa, pero funciona y se parece a la instrucción switch presente en C

while (TRUE) {
  if (is.na(val)) {
    val <- "NULL"
    break
  }
  if (inherits(val, "POSIXct") || inherits(val, "POSIXt")) {
    val <- paste0("#",  format(val, "%Y-%m-%d %H:%M:%S"), "#")
    break
  }
  if (inherits(val, "Date")) {
    val <- paste0("#",  format(val, "%Y-%m-%d"), "#")
    break
  }
  if (is.numeric(val)) break
  val <- paste0("'", gsub("'", "''", val), "'")
  break
}
Rolf L
fuente