chunjin
chunjin

Reputation: 240

combine vectors of different length into data frame in R

I have four vectors as follows:

x1=letters[1:5]
x2=c("a","b","c")
x3=c("a","b","c","d")
x4=c("a","b","e")

Actually,I want to get a data frame like this:

 data.frame(x1,x2=c("a","b","c",NA,NA),
            x3=c("a","b","c","d",NA),
           x4=c("a","b",NA,NA,"e"))
  x1   x2   x3   x4
1  a    a    a    a
2  b    b    b    b
3  c    c    c <NA>
4  d <NA>    d <NA>
5  e <NA> <NA>    e

Could someone help me or give me a function as indicators?

Upvotes: 3

Views: 732

Answers (4)

A5C1D2H2I1M1N2O1R2T1
A5C1D2H2I1M1N2O1R2T1

Reputation: 193517

There's a non-exported function charMat in my "splitstackshape" package that might be useful for something like this.

Here, I've used it in conjunction with mget:

## library(splitstackshape) # not required since you'll be using ::: anyway...
data.frame(t(splitstackshape:::charMat(mget(ls(pattern = "x\\d")), mode = "value")))
#   X1   X2   X3   X4
# a  a    a    a    a
# b  b    b    b    b
# c  c    c    c <NA>
# d  d <NA>    d <NA>
# e  e <NA> <NA>    e

Upvotes: 2

Colonel Beauvel
Colonel Beauvel

Reputation: 31161

You can do:

ll = list(x1=x1, x2=x2, x3=x3, x4=x4)
x  = unique(unlist(ll))

data.frame(lapply(ll, function(y) ifelse(is.element(x,y),x,NA)))
#  x1   x2   x3   x4
#1  a    a    a    a
#2  b    b    b    b
#3  c    c    c <NA>
#4  d <NA>    d <NA>
#5  e <NA> <NA>    e

Or alternatively, here is a one-liner:

library(reshape2)
dcast(stack(list(x1=x1, x2=x2, x3=x3, x4=x4)), values~ind, value.var='values')[-1]

Upvotes: 2

Berecht
Berecht

Reputation: 1135

A solution joining from x1 using sqldf

   require(sqldf)

    x1 <- data.frame(x1)
    x2 <- data.frame(x2)
    x3 <- data.frame(x3)
    x4 <- data.frame(x4)

    x <- sqldf('select x1.x1, x2.x2, x3.x3, x4.x4
                from x1
                left join x2 on x1.x1 = x2.x2
                left join x3 on x1.x1 = x3.x3
                left join x4 on x1.x1 = x4.x4
               ')

Upvotes: 2

etienne
etienne

Reputation: 3678

Here is a solution :

require(zoo)
l<-lapply(list(x1,x2,x3,x4),function(x){zoo(x,x)})
result<-Reduce(merge,l)
colnames(result)<-paste0('x',1:4)

result
#   x1 x2   x3   x4  
# a a  a    a    a   
# b b  b    b    b   
# c c  c    c    <NA>
# d d  <NA> d    <NA>
# e e  <NA> <NA> e   

Here , lapply combined with zoo will create a list of ordered observations. Reduce will apply merge successively to the list. The last step is to rename the columns of the result.

You can also convert result to a dataframe if that is your desired output :

result<-as.data.frame(result)
rownames(result)<-NULL

result
#   x1   x2   x3   x4
# 1  a    a    a    a
# 2  b    b    b    b
# 3  c    c    c <NA>
# 4  d <NA>    d <NA>
# 5  e <NA> <NA>    e

Note that if you have vectors x1 to x20 it could be too long to create list(x1,x2,...) so you could use sapply(paste0('x',1:4),get) instead of list(x1,x2,x3,x4).

Upvotes: 1

Related Questions