1

I have a list of matrices that I want to be able to cbind into one matrix, but I run into a problem when they have different sized rows. To fix this I am trying to add empty rows to the bottom of the shorter ones, however the second to last step isn't quite working.

## LIST OF MATRACIES
lst = list(as.matrix(data.frame(1:3, 1:3)), as.matrix(data.frame(1:2, 1:2)))

## FIND LONGEST ONE
mrow = lapply(lst, function(x) nrow(x))
mrow = max(unlist(lst))

## CREATE MATRIX LIST TO RBIND
tempM = lapply(1:length(lst), function(x) matrix(nrow = mrow - nrow(lst[x][[1]]), ncol = ncol(lst[x][[1]])))

## ADD ROWS TO SHORTER MATRICES TO MAkE LENGTHS LINE UP
## THIS IS WHERE THINGS GO WRONG
lst = lapply(1:length(tempM), function(x) rbind(lst[x][[1]], tempM[x]))

## GOAL TO BE ABLE TO: 
rlist::list.cbind(lst) ## ERROR: Different number of rows
Rafael
  • 3,096
  • 1
  • 23
  • 61

2 Answers2

1

I'm double stealing a great function from here which should do exactly what you're looking for:

cbind.fill <- function(...){
  nm <- list(...) 
  nm <- lapply(nm, as.matrix)
  n <- max(sapply(nm, nrow)) 
  do.call(cbind, lapply(nm, function (x) 
    rbind(x, matrix(, n-nrow(x), ncol(x))))) 
}

You can easily apply it to your list lst using do.call:

lst <- list(as.matrix(data.frame(1:3, 1:3)), as.matrix(data.frame(1:2, 1:2)))

do.call(cbind.fill,lst)

#      X1.  X1.3.1 X1.2 X1.2.1
# [1,]    1      1    1      1
# [2,]    2      2    2      2
# [3,]    3      3   NA     NA
Val
  • 6,585
  • 5
  • 22
  • 52
1

Another way to skin this cat:

library(tidyverse)
lst = list(as.matrix(data.frame(1:3, 1:3)),
           as.matrix(data.frame(1:2, 1:2))
           )

targheight <- reduce(lst,function(a,b){max(nrow(a),nrow(b))})
lst <- reduce(map(lst,function(x){rbind(x,matrix(nrow=targheight-dim(x)[1],ncol=dim(x)[2]))}),cbind)
steveLangsford
  • 646
  • 5
  • 9
  • Is there something that `purrr::reduce` offers here that `base::Reduce` does not? Similarly, `purrr::map` and `base::lapply`. But sticking with the `tidyverse` theme, any reason you chose `base::rbind` over `dplyr::bind_rows`? (I'm not ding-ing the `tidyverse` here, but I suggest that loading all of it when none of the functions *add* functionality might be heavy-handed. I do realize that they might be considered *safer* in some contexts, though perhaps not as relevant given the OP inputs.) – r2evans Mar 15 '18 at 19:55
  • Nothing as sophisticated as all that, I'm just using what I know, and what I know is a pretty random kludge of stuff. This is why I come to post on stackoverflow, aside from the warm fuzzies of feeling useful sometimes, people call me out on things I've missed like dplyr::bind_rows and I learn stuff! For what it's worth, all else being equal I find the dplyr idiom much more readable. I've never worked in a context where the overhead of loading the library was a concern, but I get that that's a real thing sometimes. – steveLangsford Mar 16 '18 at 14:06