[R] force apply() to return a list

Berwin A Turlach berwin at maths.uwa.edu.au
Mon Nov 21 15:29:24 CET 2005


G'day Robin,

>>>>> "RH" == Robin Hankin <r.hankin at noc.soton.ac.uk> writes:

    RH> Still, it's a little disconcerting that apply() as generally
    RH> used can return a list 99.9% of the time and a matrix the
    RH> other 0.1%.
It probably depends on how it is used. :-)

I usually use apply in situations where I know that the lengths of the
result is always the same and want a matrix returned.  Thus, in my
applications in 99.99% of the time a matrix is returned and the other
0.01% a list (and I forget that apply could return a list).

(BTW, 67.8% of all statistics are made up on the spot, just as the
last three presumably. :) )

    RH> It took me a long time to track this down when debugging my
    RH> code the other night.
It is called defensive programming (and it is great if it works). :-)
If your code expects a list, make sure that it gets a list and spits a
dummy if not, then these kind of problems are easy to find.....

    RH> Does anyone else agree?  Would it be possible to add an
    RH> argument such as force.list (with default FALSE) to apply()
    RH> that makes apply() return a list under all circumstances?
    RH> Also, adding Dimitris's excellent workaround to apply()'s
    RH> manpage would be helpful.
If you supply appropriate patches against the SVN source, I am sure
that R core will consider it.

And although Dimitris solution is quite nice, I find that it obfuscate
the code a bit.  What is wrong with checking whether the result
returned by apply is a matrix, and if so turn the matrix into a list.
Probably the easiest way to turn a matrix into a list is to use
as.data.frame(), if you want that the printed version of the object
looks like a list, then use as.list() too:


> a2 <- cbind(1:3,3:1)
> f <- function(x){1:max(x[1],4)}
> apply(a2,1,f)
     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    2    2    2
[3,]    3    3    3
[4,]    4    4    4
> res <- apply(a2,1,f)
> if(is.matrix(res)) res <- as.list(as.data.frame(res))
> res
$V1
[1] 1 2 3 4

$V2
[1] 1 2 3 4

$V3
[1] 1 2 3 4

Cheers,

        Berwin




More information about the R-help mailing list