Wave
Wave

Reputation: 1266

naming and rbinding all elements (dfs, matrices, vectors, etc.) from lists of list

I have a list with lists like this:

# output from a package function
A <- list(a = matrix(1:9,ncol=3),
          b = matrix(1:8,ncol=4),
          c = 1.5)

B <- list(a = matrix(11:19,ncol=3),
          b = matrix(11:18,ncol=4),
          c = 2.5)

# list with all outputs (from loaded=lapply(filenames, function(x) get(load(x))) )
superlist <- list(A, B))

What I would like to do is first add the name of each list item (A, B) to all second order list elements. For example B would become:

B <- list(a = cbind(matrix(11:19,ncol=3),c("B","B","B")),
           b = cbind(matrix(11:18,ncol=4),c("B","B")),
           c = c(2.5,"B"))

Then, the aim is to rbind all matrices, values or dataframes (a,b,c) with the same name together, so that I would have:

superlist <- list(a = rbind(cbind(matrix(1:9,ncol=3),c("A","A","A")),cbind(matrix(11:19,ncol=3),c("B","B","B"))),
           b = rbind(cbind(matrix(1:8,ncol=4),c("A","A")),cbind(matrix(11:18,ncol=4),c("B","B"))),
           c = rbind(c(1.5,"A"),c(2.5,"B")))

For the rbinding, the best I got is this (from rbind all dataframes in a list of lists by name):

do.call("rbind",lapply(superlist ,function(x) x[["a"]]))

However, it only does it for one list element (and I have more than 20). I know that I can write a loop, but as I will be using the function often I would like to know how to do this nicer.

I am aware that there are multiple questions asked about this, but none of them has exactly the same problem (for example, some only have data frames as list of list elements, sometimes all of the same size). So although certain questions provided a bit of help, none truly gave me enough information to resolve my problem.

Thank you

Upvotes: 0

Views: 123

Answers (1)

AEF
AEF

Reputation: 5650

I think can utilize the function proposed in this answer. It reverses the list structure i.e. groups by inner list. An example:

# output from a package function
A <- list(a = matrix(1:9,ncol=3),
      b = matrix(1:8,ncol=4),
      c = 1.5)

B <- list(a = matrix(11:19,ncol=3),
      b = matrix(11:18,ncol=4),
      c = 2.5)

# list with all outputs (from loaded=lapply(filenames, function(x)      get(load(x))) )
superlist <- list(A, B)
################### your code above ##############
## the function from the linked answer
fun <-  function(ll) {
    nms <- unique(unlist(lapply(ll, function(X) names(X))))
    ll <- lapply(ll, function(X) setNames(X[nms], nms))
    ll <- apply(do.call(rbind, ll), 2, as.list)
    lapply(ll, function(X) X[!sapply(X, is.null)])
}

## apply the function to your list
insideout <- fun(superlist)

## rbind the components together
lapply(insideout, function(x) do.call(rbind, x))

Is this what you intended to do?

Upvotes: 1

Related Questions