Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R - Using switch with logical values

switch() accepts as it's first argument

"EXPR an expression evaluating to a number or a character string."

however, can it be coerced to working with a logical? If so, am I doing something else wrong in this code?

I have a column containing logical values in a data frame, and I want to write a new column containing values from the existing data in the data frame based on the logical parameters:

exampleCurrent <- data.frame(value = c(5.5, 4.5, 4, 2.9, 2),
                         off = as.logical(c("F", "F", "T", "T", "F")),
                         extremeValue = as.logical(c("F", "F", "F", "F", "T")),
                         eclMinWork = c(5, 5.3, 5, 4.7, 3),
                         eclMinOff = c(4, 3.2, 3, 4, 3))

I would like to get to this:

exampleWanted <- data.frame(value = c(5.5, 4.5, 4, 2.9, 2),
                        off = as.logical(c("F", "F", "T", "T", "F")),
                        extremeValue = as.logical(c("F", "F", "F", "F", "T")),
                        eclMinWork = c(5, 5.3, 5, 4.7, 4),
                        eclMinOff = c(4, 3.2, 3, 4, 3),
                        output = c(5, 4.5, 3, 2.9, 3))

The rules for selecting a number are:

  1. Check off. If off is FALSE, select from either value or eclMinWork. If off is TRUE, select from either value or eclMinOff
  2. Check extremeValue. If extreneValue = FALSE, select the smaller of value and the field in step 1. If extremeValue = TRUE, select the value from the field in step 1.

I have successfully written an ifelse() that performs, though I am wondering if I can use switch instead.

exampleGenerated <- cbind(exampleCurrent, bestCase =
                          switch(exampleCurrent$off,
                                 FALSE = ifelse(exampleCurrent$value<exampleCurrent$eclMinWork,exampleCurrent$value, exampleCurrent$eclMinWork),
                                 TRUE = ifelse(exampleCurrent$value<exampleCurrent$eclMinOff,exampleCurrent$value, exampleCurrent$eclMinOff)))

The above throws an error, I am assuming as FALSE is not a character, and is not (on the face of it) a numeric or character:

Error: unexpected '=' in: switch(exampleCurrent$off, FALSE ="

However, my attempts at wrapping as.numeric and as.character around the variables have also failed. Is there a way to do it, or am I missing a fundamental mistake in my code?

like image 361
DaveRGP Avatar asked Jan 14 '15 11:01

DaveRGP


1 Answers

You don't need switch for this task. It is easier with ifelse and pmin:

tmp <- with(exampleCurrent, ifelse(off, eclMinOff, eclMinWork))
transform(exampleCurrent, 
          bestCase = ifelse(extremeValue, tmp, pmin(value, tmp)))

#   value   off extremeValue eclMinWork eclMinOff bestCase
# 1   5.5 FALSE        FALSE        5.0       4.0      5.0
# 2   4.5 FALSE        FALSE        5.3       3.2      4.5
# 3   4.0  TRUE        FALSE        5.0       3.0      3.0
# 4   2.9  TRUE        FALSE        4.7       4.0      2.9
# 5   2.0 FALSE         TRUE        3.0       3.0      3.0
like image 189
Sven Hohenstein Avatar answered Sep 28 '22 00:09

Sven Hohenstein