how to combine vectors with different length within a list in R?
Asked Answered
D

3

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
Dixiedixieland answered 5/1, 2012 at 17:8 Comment(0)
B
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
Become answered 5/1, 2012 at 17:26 Comment(5)
Could in-line the x2 assignment, and simplify it as do.call(cbind, lapply(x, '[', spp))Guaranty
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.Loiseloiter
@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.Loiseloiter
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!Dixiedixieland
@Dixiedixieland -- Since this helped, you can 'accept' the answer by clicking the checkmark to its left. Thanks.Loiseloiter
V
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.)

Vaud answered 6/1, 2012 at 0:21 Comment(0)
N
1
merge(x = x[[1]], y = x[[2]], by = "names", all.y = TRUE)
Nall answered 11/9, 2013 at 2:41 Comment(1)
Hi and welcome to SO. It's a really great practise to add a little explanation to code only answers.Middlebrow

© 2022 - 2024 — McMap. All rights reserved.