Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

"dims [product xx] do not match the length of object [xx]" error in using R function `outer`

x <- 1:9
names(x) <- paste0("x",x)
y <- 2:5
names(y) <- paste0("y",y)

fun1      <-function(a, b) {paste(class(a),b, sep = "**")} #works
funError  <-function(a, b) {paste(class(a),class(b), sep = "**")} #does not work with outer
funNoError<-function(a, b) {paste(a,class(a),class(b),b, sep = "**")}  #works with outer  

funError(1,2) #is a valid function
outer(x, y, "funError") # fails
outer(x, y, "funNoError") # works

Q1: Why does outer(x, y, "funError") not work ?

Error in dim(robj) <- c(dX, dY) : dims [product 36] do not match the length of object [1]

Q2: Why does outer(x, y, "funNoError") work ? Its pretty similar.

  • The only difference I can see is that every "result" of funError is identical ("numeric**numeric").

  • If having the same value all the time is the problem: Why does this here work?

outer(rep(0,7), 1:10, "^")


Okay, I get it:

lol  <- function(a,b) {"lol"}
lol_v<- Vectorize(lol)

outer(x, y, "lol")   # fails with same Error
outer(x, y, "lol_v") # works as expected
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I often explain outer(x, y, FUN) when both x and y are vectors with the following:

xx <- rep(x, times = length(y))
yy <- rep(y, each = length(x))
zz <- FUN(xx, yy)
stopifnot(length(zz) == length(x) * length(y))  ## length = product?
z <- matrix(zz, length(x), length(y))

funError fails because zz has length 1, while funNoError does not because "recycling rule" has been applied when you paste a (a vector with length > 1) and class(a) (a length-1 vector).

This is illustrative as you will see why outer(1:5, 1:5, "+") works but outer(1:5, 1:5, sum) fails. Basically, FUN must be able to process xx and yy element-wise. Otherwise, wrap FUN with a sugar function called Vectorize. More details are given later.

Note that "list" is also a valid mode of a vector. So outer could be used to some non-standard things like How to perform pairwise operation like `%in%` and set operations for a list of vectors.


You can pass matrices / arrays to outer, too. Given that they are just vectors with an "dim" attribute (optionally with "dimnames"), how outer works does not change.

x <- matrix(1:4, 2, 2)  ## has "dim"
y <- matrix(1:9, 3, 3)  ## has "dim"

xx <- rep(x, times = length(y))  ## xx <- rep(c(x), times = length(y))
yy <- rep(y, each = length(x))  ## yy <- rep(c(y), each = length(x))
zz <- "*"(xx, yy)
stopifnot(length(zz) == length(x) * length(y))  ## length = product?
z <- "dim<-"( zz, c(dim(x), dim(y)) )

z0 <- outer(x, y, "*")
all.equal(z, z0)
#[1] TRUE

?outer explains the code above in plain words.

 ‘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 (plus
 any arguments in ‘...’).  It must be a vectorized function (or the
 name of one) expecting at least two arguments and returning a
 value with the same length as the first (and the second).

 Where they exist, the [dim]names of ‘X’ and ‘Y’ will be copied to
 the answer, and a dimension assigned which is the concatenation of
 the dimensions of ‘X’ and ‘Y’ (or lengths if dimensions do not
 exist).

The word "vectorized" is NOT the most discussed one in R on performance. It means "vectorizing the action of a function":

## for FUN with a single argument
FUN( c(x1, x2, x3, x4) ) = c( FUN(x1), FUN(x2), FUN(x3), FUN(x4) )

## for FUN with two arguments
  FUN( c(x1, x2, x3, x4), c(y1, y2, y3, y4) )
= c( FUN(x1, y1), FUN(x2, y2), FUN(x3, y3), FUN(x4, y4) )

Some functions say "+", "*", paste behave like this, but many others don't, say class, sum, prod. The *apply family functions in R are there to help you to vectorize function action, or you can write your own loop to achieve the same effect.


Another worth reading good-quality Q & A: Why doesn't outer work the way I think it should (in R)?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...