Skip to content

outer-question

3 messages · Rau, Roland, Tony Plate

#
Dear all,

a big thanks to Thomas Lumley, James Holtman and Tony Plate for their
answers. They all pointed in the same direction => I need a vectorized
function to be applied. Hence, I will try to work with a 'wrapper'
function as described in the FAQ.

Thanks again,
Roland
+++++
This mail has been sent through the MPI for Demographic Rese...{{dropped}}
#
[following on from a thread on R-help, but my post here seems more 
appropriate to R-devel]

Would a patch to make outer() work with non-vectorized functions be
considered?  It seems to come up moderately often on the list, which
probably indicates that many many people get bitten by the same
incorrect expectation, despite the documentation and the FAQ entry.  It
looks pretty simple to modify outer() appropriately: one extra function
argument and an if-then-else clause to call mapply(FUN, ...) instead of
calling FUN directly.

Here's a function demonstrating this:

outer2 <- function (X, Y, FUN = "*", ..., VECTORIZED=TRUE)
{
     no.nx <- is.null(nx <- dimnames(X <- as.array(X)))
     dX <- dim(X)
     no.ny <- is.null(ny <- dimnames(Y <- as.array(Y)))
     dY <- dim(Y)
     if (is.character(FUN) && FUN == "*") {
         robj <- as.vector(X) %*% t(as.vector(Y))
         dim(robj) <- c(dX, dY)
     }
     else {
         FUN <- match.fun(FUN)
         Y <- rep(Y, rep.int(length(X), length(Y)))
         if (length(X) > 0)
             X <- rep(X, times = ceiling(length(Y)/length(X)))
         if (VECTORIZED)
             robj <- FUN(X, Y, ...)
         else
             robj <- mapply(FUN, X, Y, MoreArgs=list(...))
         dim(robj) <- c(dX, dY)
     }
     if (no.nx)
         nx <- vector("list", length(dX))
     else if (no.ny)
         ny <- vector("list", length(dY))
     if (!(no.nx && no.ny))
         dimnames(robj) <- c(nx, ny)
     robj
}
# Some examples
f <- function(x, y, p=1) {cat("in f\n"); (x*y)^p}
outer2(1:2, 3:5, f, 2)
outer2(numeric(0), 3:5, f, 2)
outer2(1:2, numeric(0), f, 2)
outer2(1:2, 3:5, f, 2, VECTORIZED=F)
outer2(numeric(0), 3:5, f, 2, VECTORIZED=F)
outer2(1:2, numeric(0), f, 2, VECTORIZED=F)

# Output on examples
in f
      [,1] [,2] [,3]
[1,]    9   16   25
[2,]   36   64  100
in f
      [,1] [,2] [,3]
in f

[1,]
[2,]
in f
in f
in f
in f
in f
in f
      [,1] [,2] [,3]
[1,]    9   16   25
[2,]   36   64  100
[,1] [,2] [,3]
[1,]
[2,]
If a patch to add this feature would be considered, I'd be happy to
submit one (including documentation).  If so, and if there are any
potential traps I should bear in mind, please let me know!

-- Tony Plate
Rau, Roland wrote:
#
Apologies for the cross post.  I explicitly tried to avoid this but 
somehow r-help got tacked onto the end of the To: line without my 
realizing it.

-- Tony Plate
Tony Plate wrote:
...