[R] Do NOT use ifelse() if you can use if(.) else . [was "Checking .."]

John Fox jfox at mcmaster.ca
Tue Dec 23 15:10:44 CET 2014


Hi,

Sorry to chime in late, but here's an alternative solution, without conditionals:

> obj <- list(spec=list("Fisher"=TRUE, "Tukey"=FALSE))

> obj$spec$Fisher
[1] TRUE
 
> !is.null(obj$spec$Fisher) && obj$spec$Fisher
[1] TRUE
 
> obj$spec$Pearson
NULL
 
> !is.null(obj$spec$Pearson) && obj$spec$Pearson
[1] FALSE

I hope this helps,
 John

------------------------------------------------
John Fox, Professor
McMaster University
Hamilton, Ontario, Canada
http://socserv.mcmaster.ca/jfox/
	
On Tue, 23 Dec 2014 10:05:47 +0100
 Martin Maechler <maechler at stat.math.ethz.ch> wrote:
> >>>>> Steven Yen <syen04 at gmail.com>
> >>>>>     on Sun, 14 Dec 2014 09:30:56 -0500 writes:
> >>>>> Steven Yen <syen04 at gmail.com>
> >>>>>     on Sun, 14 Dec 2014 09:30:56 -0500 writes:
> 
>     > Thanks. This worked!! :)
>     > Fisher <- ifelse(!("Fisher" %in% names(obj$spec)), FALSE, obj$spec$Fisher)
> 
> "worked",  yes.
> 
> But please --- for the mailing list archives ---
> do use better code.
> 
> Unfortunately, ifelse() is used and has been advertized much too
> often in cases where it is very sub-optimal efficiency wise. 
> ifelse(Cond, A, B)  should only be used  when the condition
> 'Cond', a logical vector can be (and typically is) of length > 1
> {and even then, it maybe a nice short cut, but often still suboptimal
>  efficiency wise ... but let's not get there}
> 
> In cases like this one when the condition 'Cond' is a
> simple TRUE or FALSE (i.e. of length 1), using
> 
> 	if(Cond) A else B
> 
> instead of
> 
> 	ifelse(Cond, A, B)
> 
> is
> 
>   1. much more R - like  [[ "everything you do is a function call" ]]
>      hence much more elegant
> 
>   2. considerably more efficient.
> 
>   3. :-) less typing: uses two "," less ;-)
> 
>   > require(microbenchmark)
>   Loading required package: microbenchmark
>   > x <- setNames(,LETTERS)
>   > y <- setNames(letters, runif(letters))
>   > z <- pi
>   > microbenchmark(r1 <- ifelse(z > 3, x, y), r2 <- if(z > 3) x else y, times=1000)
>   Unit: nanoseconds
> 			expr  min     lq     mean median     uq   max neval cld
>    r1 <- ifelse(z > 3, x, y) 4466 4971.5 5498.928   5244 5673.5 31705  1000   b
>    r2 <- if (z > 3) x else y  171  212.0  265.241    264  291.0  3130  1000  a 
>   > 
> 
> i.e., roughly a factor of 20 times more efficient
> 
> 
> Martin Maechler,
> ETH Zurich and R Core Team.
> 
> 
>     > At 08:43 AM 12/14/2014, Ben Tupper wrote:
>     >> Hi,
>     >> 
>     >> Does this work for you?  It simply tests if the name Fisher is found 
>     >> among the names of the elements of spec.
>     >> 
>     >> obj = list(spec = list)
>     >> Fisher <- ifelse(!("Fisher" %in% names(obj$spec)), FALSE, obj$spec$Fisher)
>     >> 
>     >> Cheers,
>     >> Ben
>     >> 
>     >> On Dec 14, 2014, at 8:07 AM, Steven Yen <syen04 at gmail.com> wrote:
>     >> 
>     >> > My obj does not always come with a logical variable defined. So I do
>     >> >
>     >> > my.foo <- function(obj,df,digits=5){
>     >> > if (!is.na("obj$spec$Fisher")) Fisher<-obj$spec$Fisher
>     >> > ...
>     >> > }
>     >> >
>     >> > This works when "Fisher" is defined in/passed from obj. When it 
>     >> is not, I get error:
>     >> >
>     >> > Error in (!is.na("obj$spec$Fisher")) & Fisher :
>     >> >  operations are possible only for numeric, logical or complex types
>     >> >
>     >> > I tried exist(Fisher), missing(Fisher)... to no vail. Any idea? Thanks.
> 
> ______________________________________________
> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.



More information about the R-help mailing list