[Rd] ifelse() woes ... can we agree on a ifelse2() ?

Martin Maechler maechler at stat.math.ethz.ch
Mon Aug 8 12:20:27 CEST 2016


>>>>> Uwe Ligges <ligges at statistik.tu-dortmund.de>
>>>>>     on Sun, 7 Aug 2016 09:51:58 +0200 writes:

    > On 06.08.2016 17:30, Duncan Murdoch wrote:
    >> On 06/08/2016 10:18 AM, Martin Maechler wrote:

   [.................]

    >>> Of course, an ifelse2()  should also be more efficient than
    >>> ifelse() in typical "atomic" cases.
    >> 
    >> I don't think it is obvious how to make it more efficient.  ifelse()
    >> already skips evaluation of yes or no if not needed.  (An argument could
    >> be made that it would be better to guarantee evaluation of both, but
    >> it's usually easy enough to do this explicitly, so I don't see a need.)

    > Same from here: I do not see how this can easily be made more efficient, 
    > since evaluating ony parts causes a lot of copies of objects whichs 
    > slows stuff down, hence you need some complexity in yes and no to make 
    > evaluations of parts of them more efficient on R level.

Yes, Duncan and Uwe are right, and my comment "wish" above was
mostly misleading.  Some of the many small changes to ifelse()
since its initial [1998, R version 0.63.3] simple

ifelseR0633 <- function (test, yes, no)
{
    ans <- test
    test <- as.logical(test)
    nas <- is.na(test)
    ans[ test] <- rep(yes, length = length(ans))[ test]
    ans[!test] <- rep(no,  length = length(ans))[!test]
    ans[nas] <- NA
    ans
}

were exactly for adding speed in some of these cases.

    > Anyway, to solve the problem, we may want an add argument to ifelse2() 
    > that allows for specification of the type of the result (as vapply does)?

A good idea, probably only needed / desirable if we'd consider a
C based version {as vapply} but for the moment I did not want to
go there.

The current ifelse() is nice with "pre-S3" objects, such as
as atomic (named) vectors and (dimnamed) arrays, including matrices,
by keeping most attributes for those... and does that relatively
efficiently.

What I really meant, not above, but earlier when talking about
ifelse()'s inefficiency should really *not* have been related to
this thread, I'm sorry for that confusion.

I mean the fact that many many usages of ifelse() are of the
form
	ifelse(logiFn(x), f1(x), f2(x))

  {with f1() or f2() often even being constant}

and e.g.,  in the case where logiFn(x) gives few TRUEs and f1(.)
is expensive and f2(.) very cheap (say "constant" NA), it is
much more efficient to use

     ans <- x
     Y <- logiFn(x)
     ans[ Y] <- f1(x[ Y])
     ans[!Y] <- f2(x[!Y])

as the expensive function is only called on a small subset of
the full x.

I'm working at the main topic and *am* thanking Duncan
for his conceptual analysis and the (few) proposals.

Martin

    > Best,
    > Uwe

    >> Duncan Murdoch
    >> 
    >>> 
    >>> 
    >>> Thank you for your ideas and suggestions.
    >>> Again, there's no promise of implementation coming along with this
    >>> e-mail.
    >>> 
    >>> Martin Maechler
    >>> ETH Zurich



More information about the R-devel mailing list