0

I have lists v1 and v2 with the same names:

v1: structure(list(ID = c("A1"), Name = c("A2"),.Names = c("ID", "Name") 
    ...
v2: structure(list(ID = c("B1"), Name = c("B2"),.Names = c("ID", "Name") 

I want to concatenate the lists, while keeping the names, i.e. to get something like:

v12:  structure(list(ID = c("A1","B1"), Name = c("A2","B2"), 
.Names = c("ID", "Name")

Manual concatenation works:

v12<-cbind(Map(c, v1, v2))

But, if v1 and v2 are results of applying lapply(), and are stored in a list themselves, the similar logic does not seem to work:

v<-lapply(...)
v12<-cbind(Map(c,v))

What is the best way to automate the process? For example:

v1 <- structure(list(ID = c("A1"), Name = c("A2")),.Names = c("ID", "Name"))             
v2 <-  structure(list(ID = c("B1"), Name = c("B2")),.Names = c("ID", "Name"))
v <- list(v1, v2)
k<-t(mapply(c, v))

results in:

ID  Name
A1  A2
B1  B2

not in:

  ID    Name
"A1","B1"   "A2","B2"
Alex
  • 1
  • 2
  • 2
    Your question is quite confusing. It mentions `cbind`, but I think you are actually looking for `rbind`. You mention `list`s, but it seems like you're actually referring to `data.frame`s. Can you please try to post some reproducible code. See [this post](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) for some tips. – A5C1D2H2I1M1N2O1R2T1 Oct 03 '12 at 07:31
  • Thanks to Sven, code is smth like this: 'v1 <- structure(list(ID = c("A1"), Name = c("A2")),.Names = c("ID", "Name"))v2 <- structure(list(ID = c("B1"), Name = c("B2")),.Names = c("ID", "Name")) v <- list(v1, v2)` However, t(mapply(c, v)) does not seem to work as well. – Alex Oct 03 '12 at 07:34
  • @sven-hohenstein, thanks for the reply, but your code results in: ID Name 1 A1 A2 2 B1 B2 While I desperately need: ID Name 1 "A1","A2" "B1","B2" – Alex Oct 03 '12 at 07:36
  • 1
    Your desperate need is not at all clear. What is the _structure_ of the thing you need? Showing its printed representation does NOT tell us its internal representation. – IRTFM Oct 03 '12 at 16:06

4 Answers4

1

I find your question very unclear, but maybe you can try:

setNames(Reduce(function(x, y) paste(x, y, sep = ", "), v), 
         c("ID", "Name"))
#       ID     Name 
# "A1, B1" "A2, B2"

Or, add a t() in there too:

t(setNames(Reduce(function(x, y) paste(x, y, sep = ", "), v), 
           c("ID", "Name")))
     ID       Name    
[1,] "A1, B1" "A2, B2"
A5C1D2H2I1M1N2O1R2T1
  • 190,393
  • 28
  • 405
  • 485
1

How about this?

> data.frame(ID = do.call("paste", c(lapply(v, FUN = "[", "ID"), sep = ",")), 
+    Name = do.call("paste", c(lapply(v, FUN = "[", "Name"), sep = ",")))
     ID  Name
1 A1,B1 A2,B2
Roman Luštrik
  • 69,533
  • 24
  • 154
  • 197
  • Great solution, but what if I have 100 names in the list? Should I define each one explicitly (i.e. NameX=do.call("paste", c(lapply(v, FUN = "[", "NameX"), sep = ",")), for each of Name1..Name100), or there is a faster way? – Alex Oct 03 '12 at 14:30
  • For many names, I would use a bit different approach. @mrdwab's solution is easily scalable to a lengthy list of names. If despite this you want to pursue this solution further, let us know. – Roman Luštrik Oct 03 '12 at 20:11
  • What would you recommend memory-usage-wise? – Alex Oct 03 '12 at 23:32
0

An idea::

v1 <- structure(list(ID = c("A1"), Name = c("A2")),.Names = c("ID", "Name"))
v2 <-  structure(list(ID = c("B1"), Name = c("B2")),.Names = c("ID", "Name"))
v <- list(v1, v2)


t(mapply(c, v)) # output as matrix

Second try:

unlist(apply(mapply(c,v), 1, function(x) list(unlist(x))), recursive = FALSE)
# output as list

Update: If you want to have unique values within each list, use this:

v3 <- list(ID = "B1", Name = "B3")
vx <- list(v1, v2, v3)

unlist(apply(mapply(c,vx), 1,
             function(x) list(unique(unlist(x)))), recursive = FALSE)
Sven Hohenstein
  • 80,497
  • 17
  • 145
  • 168
  • Thanks, seems to work. What if I have a few similar elements in v1 and v2, and I do not want to double-count? – Alex Oct 03 '12 at 15:09
  • @ Sven Thanks. Many thanks! I do apologize for bad wording of the question, what I meant is – if I have N exact lists in my list matrix, how do I ignore N-1 duplicates and have only 1 representative returned by the function, along with other lists? From - $ ID : chr [1:3] "A1" "B1" "B1" “A1” $ Name: chr [1:3] "A2" "B2" "B3" “A2” Desired Result- $ ID : chr [1:3] "A1" "B1" "B1" $ Name: chr [1:3] "A2" "B2" "B3" – Alex Oct 03 '12 at 23:22
  • I assume it has something to do with `duplicate`, looking into it now – Alex Oct 04 '12 at 00:43
  • @Alex Doesn't the last command of my answer produce the result you're looking for? – Sven Hohenstein Oct 04 '12 at 03:05
  • Yes, if the duplicates are stored in one row only. If not, I guess column-by-column scan using for(...) is inevitable, it seems – Alex Oct 04 '12 at 04:00
  • Could you give an example? @Alex – Sven Hohenstein Oct 04 '12 at 07:59
0

If I understand correctly you want the a list with the same structure as the other two, but with the elements merged. In which case, try this:

ul <- unlist(list(v1,v2))
sapply(unique(names(ul)),function(x) as.vector(ul[names(ul)%in%x]),simplify=FALSE)
$ID
[1] "A1" "B1"

$Name
[1] "A2" "B2"
James
  • 65,548
  • 14
  • 155
  • 193