Search code examples
rrbind

rbind.fill but in base R


I am trying to find an efficient (fast in running and simple in coding) way to do the rbind.fill function but in base R. From my searching, there seems to be plenty of library functions such as smartbind, bind_rows, and rbind on data.table, though, as stated before, I need a solution in base R. I found using:

df3 <- rbind(df1, df2[, names(df1)])

From an answer to this question, but it removes the columns while I want extra columns filled with NA to be added instead.

It would also be nice if this method works on an empty data.frame and a populated one too, essentially just setting returning the populated one. (this is for the sake of simplicity, but if it's not possible it's not hard to just replace the variable with the new data.frame if it's empty.

I would also like it to bind by column names for the columns which are labeled the same. Additionally, the first data frame can be both bigger and smaller than the second one, and both may have columns the other does not have.

Here is an example input and output I would like (I just made up the numbers they don't really matter).

#inputs
a <- data.frame(aaa=c(1, 1, 2), bbb=c(2, 3, 3), ccc=c(1, 3, 4))
b <- data.frame(aaa=c(8, 5, 4), bbb=c(1, 1, 4), ddd=c(9, 9, 9), eee=(1, 2, 4))
#desired output
aaa bbb ccc ddd eee
1   2   1   NA  NA
1   3   3   NA  NA
2   3   4   NA  NA
8   1   NA  9   1
5   1   NA  9   2
4   4   NA  9   4

Solution

  • I don't know how efficient it may be, but one simple way to code this would be to add the missing columns to each data frame and then rbind together.

    rbindx <- function(..., dfs=list(...)) {
      ns <- unique(unlist(sapply(dfs, names)))
      do.call(rbind, lapply(dfs, function(x) {
        for(n in ns[! ns %in% names(x)]) {x[[n]] <- NA}; x }))
    }
    
    a <- data.frame(aaa=c(1, 1, 2), bbb=c(2, 3, 3), ccc=c(1, 3, 4))
    b <- data.frame(aaa=c(8, 5, 4), bbb=c(1, 1, 4), ddd=c(9, 9, 9), eee=c(1, 2, 4))
    rbindx(a, b)
    
    #   aaa bbb ccc ddd eee
    # 1   1   2   1  NA  NA
    # 2   1   3   3  NA  NA
    # 3   2   3   4  NA  NA
    # 4   8   1  NA   9   1
    # 5   5   1  NA   9   2
    # 6   4   4  NA   9   4