From wdunlap at tibco.com  Fri Dec 18 20:39:41 2009
From: wdunlap at tibco.com (William Dunlap)
Date: Fri, 18 Dec 2009 11:39:41 -0800
Subject: [Rd] Vectorized switch
In-Reply-To: <8b356f880912181107g7a7295fch9d26f2161d049404@mail.gmail.com>
References: <8b356f880912181107g7a7295fch9d26f2161d049404@mail.gmail.com>
Message-ID: <77EB52C6DD32BA4D87471DCD70C8D7000243D669@NA-PA-VBE03.na.tibco.com>

> -----Original Message-----
> From: r-devel-bounces at r-project.org 
> [mailto:r-devel-bounces at r-project.org] On Behalf Of Stavros Macrakis
> Sent: Friday, December 18, 2009 11:07 AM
> To: r-devel at r-project.org
> Subject: [Rd] Vectorized switch
> 
> What is the 'idiomatic' way of writing a vectorized switch statement?
> 
> That is, I would like to write, e.g.,
> 
>          vswitch( c('a','x','b','a'),
>                       a= 1:4,
>                       b=11:14,
>                       100 )
>           => c(1, 100, 13, 4 )
> 
> equivalent to
> 
>         ifelse( c('a','x','b','a') == 'a', 1:4,
>                    ifelse( c('a','x','b','a') == 'b', 11:14,
>                               100 ) )
> 
> A simple way of doing this is (leaving aside the default case):
> 
>        colchoose <- function(frame,selector)
>            
> mapply(function(a,b)frame[a,b],seq_along(frame[1]),selector))
> 
>       colchoose( data.frame(a=1:4,b=11:14), c('a','b','b','a'))
>            => c(1,11,11,1)

I thought you would want c(1,12,13,4), not c(1,11,11,1),
out of this call.  Perhaps I misunderstand your requirements.

However, if you want c(1,12,13,4) one approach is to use
a 2-column matrix of integers as the subscript into the
main matrix (or data.frame).  E.g.,

  > f1<-function(frame, selector) {
        selector <- match(selector, colnames(frame))
        frame[cbind(seq_along(selector), selector)]
    }
  > f1(data.frame(a=1:4,b=11:14), c('a','b','b','a'))
  [1]  1 12 13  4
  > f1(cbind(a=1:4,b=11:14), c('a','b','b','a'))
  [1]  1 12 13  4

A looping approach that did not use repeated calls to
[.data.frame should also be pretty quick.  E.g.,

  f2 <- function (namedList, selector) {
      result <- namedList[[1]] # just to get class and length right
      for (n in unique(selector)) {
          i <- n == selector
          result[i] <- namedList[[n]][i]
      }
      result
  }
  > f2(list(a=1:4,b=11:14), c('a','b','b','a'))
  [1]  1 12 13  4

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com 

> 
> But of course this is not very efficient compared to the way 
> ifelse works.
> 
> Is there a standard function or idiom for this (am I missing something
> obvious?), or should I write my own?
> 
>              -s
> 
> 	[[alternative HTML version deleted]]
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
> 



[Rd] Vectorized switch
William Dunlap