Rev 40356 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
apply <- function(X, MARGIN, FUN, ...){FUN <- match.fun(FUN)## Ensure that X is an array objectd <- dim(X)dl <- length(d)if(dl == 0)stop("dim(X) must have a positive length")ds <- 1:dlif(length(oldClass(X)) > 0)X <- if(dl == 2) as.matrix(X) else as.array(X)dn <- dimnames(X)## Extract the margins and associated dimnamess.call <- ds[-MARGIN]s.ans <- ds[MARGIN]d.call <- d[-MARGIN]d.ans <- d[MARGIN]dn.call<- dn[-MARGIN]dn.ans <- dn[MARGIN]## dimnames(X) <- NULL## do the callsd2 <- prod(d.ans)if(d2 == 0) {## arrays with some 0 extents: return ``empty result'' trying## to use proper mode and dimension:## The following is still a bit `hackish': use non-empty XnewX <- array(vector(typeof(X), 1), dim = c(prod(d.call), 1))ans <- FUN(if(length(d.call) < 2) newX[,1] elsearray(newX[,1], d.call, dn.call), ...)return(if(is.null(ans)) ans else if(length(d.ans) < 2) ans[1][-1]else array(ans, d.ans, dn.ans))}## elsenewX <- aperm(X, c(s.call, s.ans))dim(newX) <- c(prod(d.call), d2)ans <- vector("list", d2)if(length(d.call) < 2) {# vectorif (length(dn.call)) dimnames(newX) <- c(dn.call, list(NULL))for(i in 1:d2) {tmp <- FUN(newX[,i], ...)if(!is.null(tmp)) ans[[i]] <- tmp}} elsefor(i in 1:d2) {tmp <- FUN(array(newX[,i], d.call, dn.call), ...)if(!is.null(tmp)) ans[[i]] <- tmp}## answer dims and dimnamesans.list <- is.recursive(ans[[1]])l.ans <- length(ans[[1]])ans.names <- names(ans[[1]])if(!ans.list)ans.list <- any(unlist(lapply(ans, length)) != l.ans)if(!ans.list && length(ans.names)) {all.same <- sapply(ans, function(x) identical(names(x), ans.names))if (!all(all.same)) ans.names <- NULL}len.a <- if(ans.list) d2 else length(ans <- unlist(ans, recursive = FALSE))if(length(MARGIN) == 1 && len.a == d2) {names(ans) <- if(length(dn.ans[[1]])) dn.ans[[1]] # else NULLreturn(ans)}if(len.a == d2)return(array(ans, d.ans, dn.ans))if(len.a > 0 && len.a %% d2 == 0) {if(is.null(dn.ans)) dn.ans <- vector(mode="list", length(d.ans))dn.ans <- c(list(ans.names), dn.ans)return(array(ans, c(len.a %/% d2, d.ans),if(!all(sapply(dn.ans, is.null))) dn.ans))}return(ans)}