Bjørn-Helge Mevik
2004-Aug-31 09:49 UTC
[Rd] Dimension of apply(X, MARGIN, FUN) when FUN returns a matrix
Dear all, apply(X, MARGIN, FUN, ...) returns an array of dimension c(n, dim(X)[MARGIN]) when FUN returns a vector of length n > 1. Matrices and arrays are also vectors, so if FUN returns a matrix or an array, apply returns an array of dimension c(n, dim(X)[MARGIN]) as above. This is in accordance with the description of apply in the Blue Book, and also how Splus works (at least v6.0). I am curious: why was it decided not to return an array of dimension c(dim(result.of.FUN), dim(X)[MARGIN]) when FUN returns a matrix or an array? (This is not meant as criticism. I am sure there is a good reason; I just cannot see it.) -- Bj?rn-Helge Mevik
Tony Plate
2004-Aug-31 17:15 UTC
[Rd] Dimension of apply(X, MARGIN, FUN) when FUN returns a matrix
Bjorn, sorry I can't answer your question, but I had the same question some time ago and ended up creating a modified version of apply() that would do something like what you suggested. It used the abind() function (from the abind package) to assemble the result. For example, if dim(X)=c(7,6,5,4) and MARGIN=c(1,2) and dim(FUN.result)==c(3,2), it would return an array with dim==c(7,6,3,2). The main tricky design issue was working out what it should do in cases with "holes" in MARGIN such as the following: * length(dim(X))==5 and MARGIN=c(1,3,5) and length(dim(FUN.result))==2 * length(dim(X))==3 and MARGIN=c(1,3) and length(dim(FUN.result))==2 * length(dim(X))==5 and MARGIN=c(1,3,5) and length(dim(FUN.result))==1 I think the approach I took was to fill in the "holes" in MARGIN in order with the dimensions of the result, with extra ones going on at the end, but I can't really remember because I don't really ever use that feature. I did this because that seemed to preserve the structure of X to the greatest degree possible. This also results in calls like enhanced.apply(X, 1, c) and enhanced.apply(X, 2, c) both returning the original matrix, in contrast to behavior of apply(). However, if anyone has any ideas about what is the most principled and useful way to assemble results, I'd be interested to hear. (FWIW, I called this function "bapply", for "array binding apply".) Note that tapply() can also be given the same treatment (as could be sapply(), though with sapply() it is just as easy to call abind(lapply(...), ...) instead). cheers, Tony Plate At Tuesday 01:49 AM 8/31/2004, you wrote:>Dear all, > >apply(X, MARGIN, FUN, ...) returns an array of dimension >c(n, dim(X)[MARGIN]) when FUN returns a vector of length n > 1. > >Matrices and arrays are also vectors, so if FUN returns a matrix or an >array, apply returns an array of dimension c(n, dim(X)[MARGIN]) as >above. This is in accordance with the description of apply in the >Blue Book, and also how Splus works (at least v6.0). > >I am curious: why was it decided not to return an array of dimension >c(dim(result.of.FUN), dim(X)[MARGIN]) when FUN returns a matrix or an >array? > >(This is not meant as criticism. I am sure there is a good reason; I >just cannot see it.) > >-- >Bj?rn-Helge Mevik > >______________________________________________ >R-devel@stat.math.ethz.ch mailing list >https://stat.ethz.ch/mailman/listinfo/r-devel
Gabor Grothendieck
2004-Aug-31 18:55 UTC
[Rd] Dimension of apply(X, MARGIN, FUN) when FUN returns a matrix
<bhs2 <at> mevik.net> writes: : : Dear all, : : apply(X, MARGIN, FUN, ...) returns an array of dimension : c(n, dim(X)[MARGIN]) when FUN returns a vector of length n > 1. : : Matrices and arrays are also vectors, so if FUN returns a matrix or an : array, apply returns an array of dimension c(n, dim(X)[MARGIN]) as : above. This is in accordance with the description of apply in the : Blue Book, and also how Splus works (at least v6.0). : : I am curious: why was it decided not to return an array of dimension : c(dim(result.of.FUN), dim(X)[MARGIN]) when FUN returns a matrix or an : array? : : (This is not meant as criticism. I am sure there is a good reason; I : just cannot see it.) : This does not answer your question but note that you can return the result as a list. In the following apply is used to turn each column of x into a 2x3 matrix returning the list of four such matrices: R> x <- matrix(1:24,6) R> apply(x, 2, function(x)list(matrix(x,2))) [[1]] [[1]][[1]] [,1] [,2] [,3] [1,] 1 3 5 [2,] 2 4 6 [[2]] [[2]][[1]] [,1] [,2] [,3] [1,] 7 9 11 [2,] 8 10 12 [[3]] [[3]][[1]] [,1] [,2] [,3] [1,] 13 15 17 [2,] 14 16 18 [[4]] [[4]][[1]] [,1] [,2] [,3] [1,] 19 21 23 [2,] 20 22 24