Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple question regarding the use of outer() and user-defined functions?

Tags:

r

> fun1 <- function(x,y){x+y}
> outer(seq(1,5,length=5),seq(6,10,length=5),fun1)
     [,1] [,2] [,3] [,4] [,5]
[1,]    7    8    9   10   11
[2,]    8    9   10   11   12
[3,]    9   10   11   12   13
[4,]   10   11   12   13   14
[5,]   11   12   13   14   15
> fun2 <- function(x,y){z<-c(x,y);z[1]+z[2]}
> outer(seq(1,5,length=5),seq(6,10,length=5),fun2)
Error in dim(robj) <- c(dX, dY) : 
  dims [product 25] do not match the length of object [1]

Why doesn't fun2() work? Aren't fun2() and fun1() essentially the same thing?

like image 962
colinfang Avatar asked Apr 05 '11 15:04

colinfang


2 Answers

As an alternative, you can just replace fun2 with Vectorize(fun2) when passing it as argument to outer:

fun2 <- function(x,y){z<-c(x,y);z[1]+z[2]}
outer(seq(1,5,length=5),seq(6,10,length=5), Vectorize(fun2))
like image 116
Daniel Bonetti Avatar answered Oct 16 '22 07:10

Daniel Bonetti


The answer becomes obvious if you read ?outer:

Details:

     ‘X’ and ‘Y’ must be suitable arguments for ‘FUN’.  Each will be
     extended by ‘rep’ to length the products of the lengths of ‘X’ and
     ‘Y’ before ‘FUN’ is called.

     ‘FUN’ is called with these two extended vectors as arguments.
     Therefore, it must be a vectorized function (or the name of one),
     expecting at least two arguments.

Think about what you are doing, you are concatenating two vectors into one vector, then sum the first and second elements of this vector. fun1() on the other hand does the vectorised sum of the inputs, so the returned object is of the same length as the individual lengths of the inputs. In fun2(), the output is a vector of length 1 and it was expecting 25.

The way to make the idea behind fun2() work is to cbind() not c() the two inputs:

> fun3 <- function(x, y) { z <- cbind(x, y); z[,1] + z[,2]}
> outer(seq(1,5,length=5),seq(6,10,length=5),fun3)
     [,1] [,2] [,3] [,4] [,5]
[1,]    7    8    9   10   11
[2,]    8    9   10   11   12
[3,]    9   10   11   12   13
[4,]   10   11   12   13   14
[5,]   11   12   13   14   15
like image 23
Gavin Simpson Avatar answered Oct 16 '22 05:10

Gavin Simpson