Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looking for a more efficient ifelse()

Tags:

r

if-statement

While R's ifelse is incredibly handy, it does have a particular shortcoming: in the call ifelse(test, yes, no) all elements of yes and no are evaluated, even those that will be thrown away.

This is rather wasteful if you're using it in the middle of a complicated numerical exercise, say in a function that will be fed to integrate, uniroot, optim or whatever. For example, one might have

ifelse(test, f(x, y, z), g(a, b, c))

where f and g are arbitrarily complex or slow functions, possibly involving more nested ifelse's.

Has anyone written a replacement for ifelse that only evaluates the elements of yes/no that will be kept? Basically, something along the lines of

out <- test
for(i in seq_along(out))
{
    if(test[i]) out[i] <- f(x[i], y[i], z[i])
    else out[i] <- g(a[i], b[i], c[i])
}

but without the clumsiness/inefficiency of an explicit loop. Is this even possible without getting into the innards of R?

like image 577
Hong Ooi Avatar asked Jan 12 '12 06:01

Hong Ooi


1 Answers

I don't think that the problem is ifelse. f and g are only being evaluated once in your expression. I think your problem is that f and g are slow with vectors.

You could change the calls to f and g so that they only get evaluated on a subset of the vector.

out <- numeric(length(test))  #or whatever the output type is
out[test] <- f(x[test], y[test], z[test])
out[!test] <- g(x[!test], y[!test], z[!test])

You'll need to adjust this if any elements of test are NA.

like image 130
Richie Cotton Avatar answered Oct 03 '22 07:10

Richie Cotton