0

I have list of lists (same lengths: n). How can I concatenate them, to get one vector of the same input length (n) ? For example I have:

[[1]] 
[1] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[[2]] 
[1] "a" "a" NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
[[3]]
[1] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA "d" "e" NA NA NA

I want to get:

"a" "a" NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA "d" "e" NA NA NA

I have tried:

Reduce('union',lapply(l,function(x){x$AB}))

But I got:

"a" NA "d" "e"

I want to get a vector with same length as the input l[[1]]$AB. Any ideas?

MrFlick
  • 195,160
  • 17
  • 277
  • 295
Cecile
  • 93
  • 10
  • Could you share you input data with `dput(x$AB)` (if `x$AB` is the name of your data object) ? That would help and clarify if your object is really a nested list. – cbo Mar 12 '20 at 16:37

4 Answers4

2

I believe you're looking for dplyr's coalesce:

library(dplyr)
mylist<-lapply(mylist,as,"character")
do.call(coalesce,mylist)
[1] "a" "a" NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  "d" "e" NA  NA  NA 

NOTE: Using your exact example, the first element on the list is automatically interpreted as logical class because it's all NAs. I added row 2 in the code above to get around that by coercing all rows in the list into a character class.

iod
  • 7,412
  • 2
  • 17
  • 36
1

We can use pmax

do.call(pmax, c(l, na.rm = TRUE))
#[1] "a" "a" NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  "d" "e" NA  NA  NA 

data

l <- list(c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA), c("a", "a", NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA), c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, "d", "e", NA, NA, NA))
akrun
  • 874,273
  • 37
  • 540
  • 662
  • Your solution `do.call(pmax, c(list_obj, na.rm = TRUE))` posted [here](https://stackoverflow.com/a/29634492/8245406) works. I am closing as duplicate. – Rui Barradas Mar 12 '20 at 16:40
  • I have upvoted the one in the link, believing that it's the right place to do it. But I can reopen/upvote this one/close :(. – Rui Barradas Mar 12 '20 at 17:41
  • It is a dupe but the question is not very clear especially wiith the `x$AB` – akrun Mar 12 '20 at 17:42
0

You could coerce list to a data frame and use ifelse case handling like this:

apply(as.data.frame(l), 1, function(x) ifelse(all(is.na(x)), NA, x[!is.na(x)]))
# [1] "a" "a" NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA 
# [17] NA  NA  "d" "e" NA  NA  NA 

Data

l <- list(c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA), c("a", "a", NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA), c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, "d", "e", NA, NA, NA))
jay.sf
  • 60,139
  • 8
  • 53
  • 110
0

You could also perform row operation with conversion to a data.frame :

list_obj <- list(rep(NA, 20), c("a", "a", rep(NA, 18)), c(rep(NA,16), "d", "e", NA, NA))
df_l <- as.data.frame(list_obj)
apply(df_l, 1, FUN = function(x) paste(ifelse(is.na(x), "", x), collapse = ""))
#>  [1] "a" "a" ""  ""  ""  ""  ""  ""  ""  ""  ""  ""  ""  ""  ""  ""  "d" "e" "" 
#> [20] ""
cbo
  • 1,664
  • 1
  • 12
  • 27