6

I have a problem when combining the following vectors included in the list:

x <- list(as.numeric(c(1,4)),as.numeric(c(3,19,11)))
names (x[[1]]) <- c("species.A","species.C")
names (x[[2]]) <- c("species.A","species.B","species.C")

which gives the following list:

>x
>[[1]]
>species.A species.C 
>         1         4 
>[[2]]
>species.A species.B species.C 
>        3        19        11 

combining them using the do.call function: y<- do.call(cbind,x)

gives:

>y
>             [,1] [,2]
>   species.A    1    3
>   species.B    4   19
>   species.C    1   11

while I would like to obtain this:

>             [,1] [,2]
>   species.A    1    3
>   species.B   NA   19
>   species.C    4   11
udo
  • 4,832
  • 4
  • 54
  • 82
Julien
  • 509
  • 1
  • 5
  • 8

3 Answers3

5

You need to give R a bit more help, by first preparing the particular vectors, all of the same length, that you eventually want to cbind together. Otherwise (as you've seen) R uses its usual recycling rules to fill out the matrix.

Try something like this:

spp <- paste("species", c("A", "B", "C"), sep=".")

x2 <- lapply(x, FUN=function(X) X[spp])
mat <- do.call("cbind", x2)
row.names(mat) <- spp

mat
          [,1] [,2]
species.A    1    3
species.B   NA   19
species.C    4   11

EDIT: As Brian mentions in comments, this could be made a bit more compact (but at the expense of some readability). Which one you use is just a matter of taste:

mat <- do.call("cbind", lapply(x, "[", spp))
row.names(mat) <- spp
Josh O'Brien
  • 159,210
  • 26
  • 366
  • 455
  • Could in-line the x2 assignment, and simplify it as `do.call(cbind, lapply(x, '[', spp))` – Brian Diggs Jan 05 '12 at 17:35
  • I broke out the assignment, and made the FUN definition more explicit for the sake of clarity, since I think it's fair to conclude that the OP is a relative newbie. But yes, this could all be done in a single line. In fact, I might as well add that as a quick edit. Thanks. – Josh O'Brien Jan 05 '12 at 17:39
  • @BrianDiggs -- No problem. It was a good suggestion, and a simple example like this is the best kind of place to introduce both of those techniques. Thanks again. – Josh O'Brien Jan 05 '12 at 17:46
  • Great! Thanks guys. Both options are interesting, the first one to understand the trick, the second one to include in my time-consumming analysis.Thanks again! – Julien Jan 05 '12 at 19:23
  • @Julien -- Since this helped, you can 'accept' the answer by clicking the checkmark to its left. Thanks. – Josh O'Brien Jan 05 '12 at 19:33
5

It looks like you're actually trying to do a merge. As such, merge will work. You just have to tell it to merge on the names, and to keep all rows.

do.call(merge, c(x, by=0, all=TRUE))   # by=0 and by="row.names" are the same

(This will create a data frame rather than a matrix, but for most purposes that shouldn't be an issue.)

Hong Ooi
  • 56,353
  • 13
  • 134
  • 187
1
merge(x = x[[1]], y = x[[2]], by = "names", all.y = TRUE)
user2759975
  • 71
  • 1
  • 2
  • 8
  • 1
    Hi and welcome to SO. It's a really great practise to add a little explanation to code only answers. – Fluffeh Sep 11 '13 at 02:59