3

I want to write a switch statement in r with three conditions but can't seem to get it to work. What am I doing wrong?

# assigning some values
test.type <- "p"
var.equal<- TRUE
  paired <- FALSE

# preparing text for which p-value adjustment method was used
test.description <- switch(
    EXPR = test.type & var.equal & paired,
    "p" & TRUE & TRUE = "Student's t-test",
    "p" & FALSE & TRUE = "Student's t-test",
    "p" & TRUE & FALSE = "Student's t-test",
    "p" & FALSE & FALSE = "Games-Howell test",
    "np" & TRUE & TRUE = "Durbin-Conover test"
  )
#> Error: <text>:10:23: unexpected '='
#> 9:     EXPR = test.type & var.equal & paired,
#> 10:     "p" & TRUE & TRUE =
#>                           ^

Created on 2018-11-08 by the reprex package (v0.2.1)

A simpler version of this statement with just one condition does work-

# simpler switch
(test.description <- switch(
  EXPR = test.type,
  "p"  = "Student's t-test",
  "np" = "Durbin-Conover test"
))
#> [1] "Student's t-test"

Created on 2018-11-08 by the reprex package (v0.2.1)

Indrajeet Patil
  • 4,673
  • 2
  • 20
  • 51

3 Answers3

4

Another solution could be to use dplyr's case_when, which uses syntax more similar to your switch statements:

library(dplyr)

## initial dataframe
df <- data.frame(
  test.type = c("p", "p", "p", "p", "np", "np"),
  var.equal = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE),
  paired = c(TRUE, TRUE, FALSE, FALSE, TRUE, FALSE)
  ) 

## add column test.description 
mutate(df,
  test.description = case_when(
      test.type == "p" & !var.equal & !paired  ~ "Games-Howell test",
      test.type == "p"                         ~ "Student's t-test",
      test.type == "np" & var.equal & paired   ~ "Durbin-Conover test",
      TRUE                                     ~ "Unknown combination"
     )
)
Joris C.
  • 5,721
  • 3
  • 12
  • 27
3

That's not how R's switch() function works. Syntactically, it's just a function call, so the selectors have to be things that can be treated as names, not expressions like "p" & TRUE & TRUE. So your first switch could switch on test.type, and then use if statements to choose values based on var.equal and paired. But it would probably look better as a sequence of if statements, like this:

test.description <- 
    if (test.type == "p" && !var.equal && !paired) "Games-Howell test" else
    if (test.type == "p")                          "Student's t-test" else
    if (test.type == "np" && var.equal && paired)  "Durbin-Conover test" else
                                                   "Unknown combination"

Some things to note here:

  • You can use if statements in an expression to produce a value; this is one big statement.
  • If the else keywords were moved to the next lines, it wouldn't work, because the code up to there is a complete statement, so the else clauses would be left dangling. (There are exceptions to this, but don't rely on them.)
  • You should almost always use the scalar && within an if test rather than the vector &.
  • Another way to format this is to put the values in braces, with the closing brace and the else on the next line. I like the formatting above a little better, but your preference may vary.
user2554330
  • 37,248
  • 4
  • 43
  • 90
  • I find `if-else` statement really unappealing and prone to errors, so was looking for an alternative. I find `switch` statements much more intuitive. But there doesn't seem to be a way around `if-else` it seems. – Indrajeet Patil Nov 19 '18 at 02:16
2

Just do this:

test.type <- "p"
var.equal<- TRUE
  paired <- FALSE

test.description <- switch(
    EXPR = paste(test.type, var.equal, paired),
    "p TRUE TRUE" = "Student's t-test",
    "p FALSE TRUE" = "Student's t-test",
    "p TRUE FALSE" = "Student's t-test",
    "p FALSE FALSE" = "Games-Howell test",
    "np TRUE TRUE" = "Durbin-Conover test"
  )

Then:

test.description
[1] "Student's t-test"
Alan Gómez
  • 211
  • 1
  • 6