Alex Rivera | Logout

R idiom for switch/case

Asked 2012-05-07T18:57:34.850
19

I've got some R code that looks basically like this:

compute.quantiles <- function(mu, type) {

  ## 'mu' and 'type' are vectors of the same length

  var <- ifelse(type=='a', 6.3523 * mu^2,
         ifelse(type=='b', 234.23 * mu,
         ifelse(type=='c', {s <- 9.8 * ((mu-0.3)/3)^(6/7)+0.19; mu + mu^2/s},
         ifelse(type=='d', 56.345 * mu^1.5,
         ifelse(type=='e', 0.238986 * mu^2,
         ifelse(type=='f', mu + 1.1868823 * mu^2,
         NA ))))))

  # ...then do something with var...
}

Some sample input & output:

print(compute.quantiles(2:4, c('c','d','e')))
[1]   2.643840 292.777208   3.823776

That works correctly, but it's kind of ugly with the deep nesting, so I'm wondering if there's a different idiom that works better. Anyone have a suggestion? If switch() accepted a vector as its first argument, that would work nicely, but it just takes a scalar.

Edit
Report

1 Answer

0

I couldn't resist adding another answer with a completely different approach. Here it is.

## Sort of a cross between tapply() and ave()
tswitch <- function(x, INDEX, ...) {
  l <- substitute(list(...))
  s <- split(x, INDEX)
  pf <- parent.frame()
  split(x, INDEX) <- lapply(names(s), function(n) 
    eval(l[[n]], list(x=s[[n]]), pf)
  )
  x
}

compute.quantiles <- function(mu, type) {
  stopifnot(length(mu) == length(type))

  tswitch(mu, type,
    a = 6.3523 * x^2,
    b = 234.23 * x,
    c = x + x^2/(9.8 * ((x-0.3)/3)^(6/7)+0.19),
    d = 56.345 * x^1.5,
    e = 0.238986 * x^2,
    f = x + 1.1868823 * x^2)
}

And the sample input & output:

> compute.quantiles(2:4, c('c','d','e'))
[1]   2.643840 292.777208   3.823776

The advantage to this implementation is that it only computes the length(mu) specific values that need to be computed. By contrast, the vswitch method above computes length(mu) * M values, where M is the number of "cases" in the switch. So if the computations are costly, or if the data is big, this version could be a win.

answered 2012-05-14T18:13:18.040

Your Answer