Dear R users, can someone help with these short puzzles? 1) Is there a function like outer() that evaluates a three-argument function on a threedimensional grid - or else how to define such a function, say, outer.3()? E.g., calculate (x/y)^z on (x,y,z) element of {1,2,3}x{3,4}x{4,5} and return the results in a 3-dimensional array. I would naively use outer() on two of the arguments within a for() loop for the third argument and somehow glue the array together. Is there a better way? What about outer.4(), or even outer.n(), generalizing outer() to functions with an arbitrary number of arguments? 2) Define a function dimnames.outer() such that dimnames.outer(x, y, "*") returns, for x <- 1:2, y <- 2:3, the following matrix: y x 2 3 1 2 3 2 4 6 (Or does such such a function already exist?) 3) How to combine puzzle 1 and puzzle 2? A function dimnames.outer.n() would be a nice little tool. 4) How can I access, within a function, the name of a variable that I have passed to the function? E.g., letting a <- 2, and subsequently calling function f(a) as defined below, f <- function (x) { # How can I get "a" out of x? } 5) Finally: Letting x <- 2, how can I transform "x+y" into "2+y" (as some suitable object), or generally "func(x,y)" into "func(2,y)"? Many thanks, Marc -- Jetzt ein- oder umsteigen und USB-Speicheruhr als Pr?mie sichern!
Marc Vandemeulebroecke wrote:> Dear R users, > > can someone help with these short puzzles? > > 1) Is there a function like outer() that evaluates a three-argument function > on a threedimensional grid - or else how to define such a function, say, > outer.3()? E.g., calculate (x/y)^z on (x,y,z) element of {1,2,3}x{3,4}x{4,5} and > return the results in a 3-dimensional array. I would naively use outer() on > two of the arguments within a for() loop for the third argument and somehow > glue the array together. Is there a better way? What about outer.4(), or even > outer.n(), generalizing outer() to functions with an arbitrary number of > arguments? > > 2) > Define a function dimnames.outer() such that dimnames.outer(x, y, "*") > returns, for x <- 1:2, y <- 2:3, the following matrix: > > y > x 2 3 > 1 2 3 > 2 4 6 > > (Or does such such a function already exist?) > > 3) > > How to combine puzzle 1 and puzzle 2? A function dimnames.outer.n() would be > a nice little tool. >Here's what I came up with. If you need the other functions you mentioned, you can extract them from this example. outer.3 <- function(x, y, z, FUN, ...) { print(deparse(substitute(x))) # for question 2 n.x <- NROW(x) n.y <- NROW(y) n.z <- NROW(z) nm.x <- if(is.array(x)) dimnames(x)[[1]] else names(x) nm.y <- if(is.array(y)) dimnames(y)[[1]] else names(y) nm.z <- if(is.array(z)) dimnames(z)[[1]] else names(z) X <- expand.grid(x = x, y = y, z = z) f <- FUN(X$x, X$y, X$z, ...) array(f, dim = c(n.x, n.y, n.z), dimnames = list(nm.x, nm.y, nm.z)) } a <- 1:3 b <- 3:4 c <- 4:5 names(a) <- a names(b) <- b names(c) <- c outer.3(a, b, c, function(x, y, z) (x/y)^z) outer.3(as.matrix(a), as.matrix(b), as.matrix(c), function(x, y, z) (x/y)^z)> 4) > > How can I access, within a function, the name of a variable that I have > passed to the function? E.g., letting a <- 2, and subsequently calling function > f(a) as defined below, > > f <- function (x) { > # How can I get "a" out of x? > } >Use deparse(substitute(x)). See example above.> 5) > > Finally: Letting x <- 2, how can I transform "x+y" into "2+y" (as some > suitable object), or generally "func(x,y)" into "func(2,y)"? >Use substitute(func(x, y), list(x = 2)). Hope this is useful, Sundar
I'll try #1. You can use outer twice: outer(outer(x,y, "/"),z,function(a,b),"^") In general I suppose you could write an "outer.n" function that would take the vectors and the functions to be applied and loop through them. And I think that outer will then take care of the dimnames for you. (Taking care of #2, and, I think, #3.) Hope this helps. Matt Wiener -----Original Message----- From: Marc Vandemeulebroecke [mailto:vandemem at gmx.de] Sent: Friday, July 11, 2003 7:48 AM To: r-help at stat.math.ethz.ch Subject: [R] short puzzles Dear R users, can someone help with these short puzzles? 1) Is there a function like outer() that evaluates a three-argument function on a threedimensional grid - or else how to define such a function, say, outer.3()? E.g., calculate (x/y)^z on (x,y,z) element of {1,2,3}x{3,4}x{4,5} and return the results in a 3-dimensional array. I would naively use outer() on two of the arguments within a for() loop for the third argument and somehow glue the array together. Is there a better way? What about outer.4(), or even outer.n(), generalizing outer() to functions with an arbitrary number of arguments? 2) Define a function dimnames.outer() such that dimnames.outer(x, y, "*") returns, for x <- 1:2, y <- 2:3, the following matrix: y x 2 3 1 2 3 2 4 6 (Or does such such a function already exist?) 3) How to combine puzzle 1 and puzzle 2? A function dimnames.outer.n() would be a nice little tool. 4) How can I access, within a function, the name of a variable that I have passed to the function? E.g., letting a <- 2, and subsequently calling function f(a) as defined below, f <- function (x) { # How can I get "a" out of x? } 5) Finally: Letting x <- 2, how can I transform "x+y" into "2+y" (as some suitable object), or generally "func(x,y)" into "func(2,y)"? Many thanks, Marc -- Jetzt ein- oder umsteigen und USB-Speicheruhr als Pr?mie sichern! ______________________________________________ R-help at stat.math.ethz.ch mailing list https://www.stat.math.ethz.ch/mailman/listinfo/r-help ------------------------------------------------------------------------------ Notice: This e-mail message, together with any attachments, ...{{dropped}}
Thanks to Andy Liaw, Patrick Burns, Sundar Dorai-Raj and Matthiew Wiener for the answers to my puzzles. Here is a summary: ****************** The original question: ******************> Dear R users, > > can someone help with these short puzzles? > > 1) Is there a function like outer() that evaluates a three-argument > function > on a threedimensional grid - or else how to define such a function, say, > outer.3()? E.g., calculate (x/y)^z on (x,y,z) element of > {1,2,3}x{3,4}x{4,5} > and > return the results in a 3-dimensional array. I would naively use outer() > on > two of the arguments within a for() loop for the third argument and > somehow > glue the array together. Is there a better way? What about outer.4(), or > even > outer.n(), generalizing outer() to functions with an arbitrary number of > arguments? > > 2) > Define a function dimnames.outer() such that dimnames.outer(x, y, "*") > returns, for x <- 1:2, y <- 2:3, the following matrix: > > y > x 2 3 > 1 2 3 > 2 4 6 > > (Or does such such a function already exist?) > > 3) > > How to combine puzzle 1 and puzzle 2? A function dimnames.outer.n() would > be > a nice little tool. > > 4) > > How can I access, within a function, the name of a variable that I have > passed to the function? E.g., letting a <- 2, and subsequently calling > function > f(a) as defined below, > > f <- function (x) { > # How can I get "a" out of x? > } > > 5) > > Finally: Letting x <- 2, how can I transform "x+y" into "2+y" (as some > suitable object), or generally "func(x,y)" into "func(2,y)"? > > Many thanks, > Marc >******************** Answer to 5 ********************** The solution is of course substitute(func(x, y), list(x = 2)) ******************** Answer to 4 ********************** This was easy, too: deparse(substitute(x)) ************* Answer to 1 in easy situations **************** Where the three arguments are easily isolated, outer() can be used twice: outer(outer(a,b, "/"),c,"^") **************** Answer to 1, 2 and 3 ****************** A valuable idea came from Sundar Dorai-Raj who uses expand.grid() and then transforms the grid into a matrix. Here is his code: outer.3 <- function(x, y, z, FUN, ...) { print(deparse(substitute(x))) # for question 2 n.x <- NROW(x) n.y <- NROW(y) n.z <- NROW(z) nm.x <- if(is.array(x)) dimnames(x)[[1]] else names(x) nm.y <- if(is.array(y)) dimnames(y)[[1]] else names(y) nm.z <- if(is.array(z)) dimnames(z)[[1]] else names(z) X <- expand.grid(x = x, y = y, z = z) f <- FUN(X$x, X$y, X$z, ...) array(f, dim = c(n.x, n.y, n.z), dimnames = list(nm.x, nm.y, nm.z)) } a <- 1:3 b <- 3:4 c <- 4:5 names(a) <- a names(b) <- b names(c) <- c outer.3(a, b, c, function(x, y, z) (x/y)^z) outer.3(as.matrix(a), as.matrix(b), as.matrix(c), function(x, y, z) (x/y)^z) Finally, I have included the following code in my Rprofile. Here only vector arguments are allowed, the dimnames are handeled in a slightly different manner, and the choice of creating dimnames is controlled by the logical argument dn. outer.2 <- function (x, y, f, dn=TRUE, ...) { if (!(is.vector(x) && is.vector(y) && is.numeric(x) && is.numeric(y))) { stop("arguments not numeric vectors") } ### The suitability of f is not checked ### result <- outer(x, y, f, ...) if (dn) { lab.x <- deparse(substitute(x)) lab.y <- deparse(substitute(y)) dimnames(result) <- list(x, y) names(dimnames(result)) <- c(lab.x, lab.y) } result } outer.3 <- function(x, y, z, f, dn=TRUE, ...) { if (!(is.vector(x) && is.vector(y) && is.vector(z) && is.numeric(x) && is.numeric(y) && is.numeric(z))) { stop("arguments not numeric vectors") } ### The suitability of f is not checked ### X <- expand.grid(x=x, y=y, z=z) temp <- f(X$x, X$y, X$z, ...) result <- array(temp, dim = c(length(x), length(y), length(z))) if (dn) { lab.x <- deparse(substitute(x)) lab.y <- deparse(substitute(y)) lab.z <- deparse(substitute(z)) dimnames(result) <- list(x, y, z) names(dimnames(result)) <- c(lab.x, lab.y, lab.z) } result } A similar function outer.4() is straightforward. -- Jetzt ein- oder umsteigen und USB-Speicheruhr als Pr?mie sichern!