Michael Friendly
2010-Nov-27 22:56 UTC
[R] return vector of element names for vector, matrix or array
Just as as.vector() takes a vector, matrix or array and returns a vector in row-major order, I'd like to write a function to take such an object and return the dimension names, pasted with some separator, as a similar vector. Here is something ugly cobbled together to demonstrate what I want: a function to work for any number of dimensions. vecnames <- function(x, sep=':') { if (is.vector(x) || length(dim(x))==1) return(names(x)) else if (length(dim(x)==2)) { snames <- dimnames(x) return (as.vector(outer(snames[[1]], snames[[2]], paste, sep=sep))) } else { stop("How to handle 3+ dimensions?") } } > x1 <- c(a=1, b=2, c=3) > vecnames(x1) [1] "a" "b" "c" > > x2 <- matrix(rpois(2 * 3, 7), ncol = 3, nrow = 2) > dimnames(x2) <- list(R=letters[1:2], C=LETTERS[1:3]) > vecnames(x2) [1] "a:A" "b:A" "a:B" "b:B" "a:C" "b:C" > > x3 <- array(rpois(2 * 3 * 2, 7), dim=c(2,3,2)) > dimnames(x3)=list(R=letters[1:2], C=LETTERS[1:3], L=tail(letters,2)) > > # wanted for this case: > as.vector(outer(vecnames(x2), dimnames(x3)[[3]], paste, sep=':')) [1] "a:A:y" "b:A:y" "a:B:y" "b:B:y" "a:C:y" "b:C:y" "a:A:z" "b:A:z" "a:B:z" "b:B:z" "a:C:z" "b:C:z" > -- Michael Friendly Email: friendly AT yorku DOT ca Professor, Psychology Dept. York University Voice: 416 736-5115 x66249 Fax: 416 736-5814 4700 Keele Street Web: http://www.datavis.ca Toronto, ONT M3J 1P3 CANADA
Joshua Wiley
2010-Nov-27 23:13 UTC
[R] return vector of element names for vector, matrix or array
Hi Dr. Friendly, On Sat, Nov 27, 2010 at 2:56 PM, Michael Friendly <friendly at yorku.ca> wrote:> ?Just as as.vector() takes a vector, matrix or array and returns a vector in > row-major order, > I'd like to write a function to take such an object and return the dimension > names, > pasted with some separator, as a similar vector. > > Here is something ugly cobbled together to demonstrate what I want: a > function to work > for any number of dimensions. > > vecnames <- function(x, sep=':') { > ? ?if (is.vector(x) || length(dim(x))==1) return(names(x)) > ? ?else if (length(dim(x)==2)) { > ? ? ?snames <- dimnames(x) > ? ? ? ?return (as.vector(outer(snames[[1]], snames[[2]], paste, sep=sep))) > ? ? ? ?} > ? ?else { > ? ? ?stop("How to handle 3+ dimensions?") > ? ? ? ?} > ? ?}Interesting use of outer, but I think you're overthinking it ;) expand.grid(dimnames(x3)) If you want it as a vector separated by colons... apply(expand.grid(dimnames(x3)), 1, paste, collapse = ":") Cheers, Josh> >> x1 <- c(a=1, b=2, c=3) >> vecnames(x1) > [1] "a" "b" "c" >> >> x2 <- matrix(rpois(2 * 3, 7), ncol = 3, nrow = 2) >> dimnames(x2) <- list(R=letters[1:2], C=LETTERS[1:3]) >> vecnames(x2) > [1] "a:A" "b:A" "a:B" "b:B" "a:C" "b:C" >> >> x3 <- array(rpois(2 * 3 * 2, 7), dim=c(2,3,2)) >> dimnames(x3)=list(R=letters[1:2], C=LETTERS[1:3], L=tail(letters,2)) >> >> # wanted for this case: >> as.vector(outer(vecnames(x2), dimnames(x3)[[3]], paste, sep=':')) > ?[1] "a:A:y" "b:A:y" "a:B:y" "b:B:y" "a:C:y" "b:C:y" "a:A:z" "b:A:z" "a:B:z" > "b:B:z" "a:C:z" "b:C:z" >> > > -- > Michael Friendly ? ? Email: friendly AT yorku DOT ca > Professor, Psychology Dept. > York University ? ? ?Voice: 416 736-5115 x66249 Fax: 416 736-5814 > 4700 Keele Street ? ?Web: ? http://www.datavis.ca > Toronto, ONT ?M3J 1P3 CANADA > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.-- Joshua Wiley Ph.D. Student, Health Psychology University of California, Los Angeles http://www.joshuawiley.com/