Dear List,
Given,
y <- matrix(c(0,1,1,1,0,0,0,4,4), ncol = 3, byrow = TRUE)
rownames(y) <- c("a","b","c")
colnames(y) <- c("1","2","3")
y
y2 <- y[2:3, ]
rownames(y2) <- c("x","z")
y2
how can I stop
merge(y, y2, all = TRUE, sort = FALSE)
squishing the extra rows? Ideally I want the same as:
rbind(y, y2)
in this case. This is specific example of situation where two data
matrices have same column variables and all I want is to stick the two
sets of rows together, but I have been using merge for cases such as the
one below, where the second matrix has extra column(s):
y3 <- matrix(c(0,1,1,1,0,0,0,4,4,5,6,7), ncol = 4, byrow = TRUE)
rownames(y3) <- c("d","e","f")
colnames(y3) <- c("1","2","3","4")
y3
merge(y, y3, all = TRUE, sort = FALSE)
We don't know before hand if the columns will match. But I see now that
even this doesn't work as I was expecting/thinking!
So I'm looking for a general way to merge two matrices such that the
number of rows in the merged matrix is nrow(mat1) + nrow(mat2) and the
number of columns in the merged matrix is length(unique(colnames(mat1),
colnames(mat2).
Is there a function in R to do this, or can someone suggest a way to
achieve this? My R version info is at the end.
Just to be clear, for the y, y3 example I want something like this
returned:
1 2 3 4
a 0 1 1 NA
b 1 0 0 NA
c 0 4 4 NA
d 0 1 1 1
e 0 0 0 4
f 4 5 6 7
and for the y, y2 example, I want something like this returned:
1 2 3
a 0 1 1
b 1 0 0
c 0 4 4
x 1 0 0
z 0 4 4
Many thanks,
Gav
> version
_
platform i686-pc-linux-gnu
arch i686
os linux-gnu
system i686, linux-gnu
status Patched
major 2
minor 3.0
year 2006
month 05
day 03
svn rev 37978
language R
version.string Version 2.3.0 Patched (2006-05-03 r37978)
--
%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%
* Note new Address, Telephone & Fax numbers from 6th April 2006 *
%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%
Gavin Simpson
ECRC & ENSIS [t] +44 (0)20 7679 0522
UCL Department of Geography [f] +44 (0)20 7679 0565
Pearson Building [e] gavin.simpsonATNOSPAMucl.ac.uk
Gower Street [w] http://www.ucl.ac.uk/~ucfagls/cv/
London, UK. [w] http://www.ucl.ac.uk/~ucfagls/
WC1E 6BT.
%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%~%
Gavin Simpson wrote:> Dear List, > > Given, > > y <- matrix(c(0,1,1,1,0,0,0,4,4), ncol = 3, byrow = TRUE) > rownames(y) <- c("a","b","c") > colnames(y) <- c("1","2","3") > y > y2 <- y[2:3, ] > rownames(y2) <- c("x","z") > y2 > > how can I stop > > merge(y, y2, all = TRUE, sort = FALSE) > > squishing the extra rows? Ideally I want the same as: > > rbind(y, y2) > > in this case. This is specific example of situation where two data > matrices have same column variables and all I want is to stick the two > sets of rows together, but I have been using merge for cases such as the > one below, where the second matrix has extra column(s): > > y3 <- matrix(c(0,1,1,1,0,0,0,4,4,5,6,7), ncol = 4, byrow = TRUE) > rownames(y3) <- c("d","e","f") > colnames(y3) <- c("1","2","3","4") > y3 > merge(y, y3, all = TRUE, sort = FALSE) > > We don't know before hand if the columns will match. But I see now that > even this doesn't work as I was expecting/thinking! > > So I'm looking for a general way to merge two matrices such that the > number of rows in the merged matrix is nrow(mat1) + nrow(mat2) and the > number of columns in the merged matrix is length(unique(colnames(mat1), > colnames(mat2). > > Is there a function in R to do this, or can someone suggest a way to > achieve this? My R version info is at the end. > > Just to be clear, for the y, y3 example I want something like this > returned: > > 1 2 3 4 > a 0 1 1 NA > b 1 0 0 NA > c 0 4 4 NA > d 0 1 1 1 > e 0 0 0 4 > f 4 5 6 7 > > and for the y, y2 example, I want something like this returned: > > 1 2 3 > a 0 1 1 > b 1 0 0 > c 0 4 4 > x 1 0 0 > z 0 4 4 > > Many thanks, > > Gav > > >>version > > _ > platform i686-pc-linux-gnu > arch i686 > os linux-gnu > system i686, linux-gnu > status Patched > major 2 > minor 3.0 > year 2006 > month 05 > day 03 > svn rev 37978 > language R > version.string Version 2.3.0 Patched (2006-05-03 r37978)Will this help: rbind.all <- function(...) { x <- list(...) cn <- unique(unlist(lapply(x, colnames))) for(i in seq(along = x)) { if(any(m <- !cn %in% colnames(x[[i]]))) { na <- matrix(NA, nrow(x[[i]]), sum(m)) dimnames(na) <- list(rownames(x[[i]]), cn[m]) x[[i]] <- cbind(x[[i]], na) } } do.call(rbind, x) } y <- matrix(c(0,1,1,1,0,0,0,4,4), ncol = 3, byrow = TRUE) rownames(y) <- c("a","b","c") colnames(y) <- c("1","2","3") y2 <- y[2:3, 2:3] rownames(y2) <- c("x","z") y3 <- matrix(c(0,1,1,1,0,0,0,4,4,5,6,7), ncol = 4, byrow = TRUE) rownames(y3) <- c("d","e","f") colnames(y3) <- c("1","2","3","4") rbind.all(y, y2, as.data.frame(y3)) It does very little error-checking, so be careful how you use it. --sundar
On Tue, 2006-05-30 at 19:08 +0100, Gavin Simpson wrote:> Dear List, > > Given, > > y <- matrix(c(0,1,1,1,0,0,0,4,4), ncol = 3, byrow = TRUE) > rownames(y) <- c("a","b","c") > colnames(y) <- c("1","2","3") > y > y2 <- y[2:3, ] > rownames(y2) <- c("x","z") > y2 > > how can I stop > > merge(y, y2, all = TRUE, sort = FALSE) > > squishing the extra rows? Ideally I want the same as: > > rbind(y, y2) > > in this case. This is specific example of situation where two data > matrices have same column variables and all I want is to stick the two > sets of rows together, but I have been using merge for cases such as the > one below, where the second matrix has extra column(s): > > y3 <- matrix(c(0,1,1,1,0,0,0,4,4,5,6,7), ncol = 4, byrow = TRUE) > rownames(y3) <- c("d","e","f") > colnames(y3) <- c("1","2","3","4") > y3 > merge(y, y3, all = TRUE, sort = FALSE) > > We don't know before hand if the columns will match. But I see now that > even this doesn't work as I was expecting/thinking! > > So I'm looking for a general way to merge two matrices such that the > number of rows in the merged matrix is nrow(mat1) + nrow(mat2) and the > number of columns in the merged matrix is length(unique(colnames(mat1), > colnames(mat2). > > Is there a function in R to do this, or can someone suggest a way to > achieve this? My R version info is at the end. > > Just to be clear, for the y, y3 example I want something like this > returned: > > 1 2 3 4 > a 0 1 1 NA > b 1 0 0 NA > c 0 4 4 NA > d 0 1 1 1 > e 0 0 0 4 > f 4 5 6 7 > > and for the y, y2 example, I want something like this returned: > > 1 2 3 > a 0 1 1 > b 1 0 0 > c 0 4 4 > x 1 0 0 > z 0 4 4Gavin, Here is a possible solution, though not fully tested. It uses the "row.names" for the two matrices as part of the 'by' matching process. This is noted in the "Details" section in ?merge. So for y and y2:> res <- merge(y, y2,by = c("row.names", intersect(colnames(y), colnames(y2))), all = TRUE) # Note that the row names are now the first col> resRow.names 1 2 3 1 a 0 1 1 2 b 1 0 0 3 c 0 4 4 4 x 1 0 0 5 z 0 4 4 # Subset res, leaving out the first col> mat <- res[, -1]# Set the rownames from res> rownames(mat) <- res[, 1]> mat1 2 3 a 0 1 1 b 1 0 0 c 0 4 4 x 1 0 0 z 0 4 4