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) 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]]
My understanding is that all the really fast vectorized operations are implemented down in C code, not in R. Thus if you wanted to write a vectorized switch, which I agree would be rather nice to have, you'd need to do it down there and then write a .Call wrapper for it in R. The ifelse (C) code would probably be a good place to start looking in terms of how to write it. Gabe On Fri, Dec 18, 2009 at 11:07 AM, Stavros Macrakis <macrakis@alum.mit.edu>wrote:> 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) > > 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@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel >[[alternative HTML version deleted]]
> -----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 >