Skip to content

Unexpected behaviour of apply()

4 messages · Pierrick Bruneau, Milan Bouchet-Valat, Patrick Burns

#
Le vendredi 08 mars 2013 ? 09:29 +0100, Pierrick Bruneau a ?crit :
This is essentially which(), what did you write such a convoluted
function to get the same result?
If each call to ?FUN? returns a vector of length ?n?, then ?apply?
     returns an array of dimension ?c(n, dim(X)[MARGIN])? if ?n > 1?.
     If ?n? equals ?1?, ?apply? returns a vector if ?MARGIN? has length
     1 and an array of dimension ?dim(X)[MARGIN]? otherwise.  If ?n? is
     ?0?, the result has length 0 but not necessarily the ?correct?
     dimension.

Note especially the last sentence.
One of the interests of apply() is that it combines the return values
from all function calls into a convenient form, but this can indeed be a
problem if you cannot know in advance what this form will be. If you
need a list in all cases, then just call lapply():
lapply(seq(nrow(mat)), function(i) which(mat[i,]))


Regards
#
This is nice fodder for 'The R Inferno' -- thanks.

As Milan said, 'which' will suffice as the function.

Here is a specialized function that only returns a
list and is only implemented to work with matrices.
It should solve your current dilemma.

applyL <-
function (X, MARGIN, FUN, ...)
{
         stopifnot(length(dim(X)) == 2, length(MARGIN) == 1)

         FUN <- match.fun(FUN)
         ans <- vector("list", dim(X)[MARGIN])
         if(MARGIN == 1) {
                 for(i in seq_along(ans)) {
                         ans[[i]] <- FUN(X[i,], ...)
                 }
         } else {
                 for(i in seq_along(ans)) {
                         ans[[i]] <- FUN(X[,i], ...)
                 }
         }
         names(ans) <- dimnames(X)[[MARGIN]]
         ans
}


Pat
On 08/03/2013 08:29, Pierrick Bruneau wrote: