cbind a dataframe with an empty dataframe - cbind.fill?

36,333

Solution 1

Here's a cbind fill:

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))))) 
}

Let's try it:

x<-matrix(1:10,5,2)
y<-matrix(1:16, 4,4)
z<-matrix(1:12, 2,6)

cbind.fill(x,y)
cbind.fill(x,y,z)
cbind.fill(mtcars, mtcars[1:10,])

I think I stole this from somewhere.

EDIT STOLE FROM HERE: LINK

Solution 2

While, I think Tyler's solution is direct and the best here, I just provide the other way, using rbind.fill() that we already have.

require(plyr) # requires plyr for rbind.fill()
cbind.fill <- function(...) {                                                                                                                                                       
  transpoted <- lapply(list(...),t)                                                                                                                                                 
  transpoted_dataframe <- lapply(transpoted, as.data.frame)                                                                                                                         
  return (data.frame(t(rbind.fill(transpoted_dataframe))))                                                                                                                          
} 

Solution 3

Using rowr::cbind.fill

rowr::cbind.fill(df1,df2,fill = NA)
   A B
1  1 1
2  2 2
3  3 3
4  4 4
5  5 5
6 NA 6

Solution 4

cbind.na from the qpcR package can do that.

    install.packages("qpcR")
    library(qpcR)
    qpcR:::cbind.na(1, 1:7)

Solution 5

When a and b are data frames, following should work just fine:

ab <- merge(a, b, by="row.names", all=TRUE)[,-1]

or another possibility:

rows <- unique(c(rownames(a), rownames(b)))
ab <- cbind(a[rows ,], b[rows ,])
Share:
36,333
Xu Wang
Author by

Xu Wang

Updated on September 02, 2021

Comments

  • Xu Wang
    Xu Wang almost 3 years

    I think I'm looking for an analog of rbind.fill (in Hadley's plyr package) for cbind. I looked, but there is no cbind.fill.

    What I want to do is the following:

    #set these just for this example
    one_option <- TRUE
    diff_option <- TRUE
    
    return_df <- data.frame()
    
    if (one_option) {
        #do a bunch of calculations, produce a data.frame, for simplicity the following small_df
        small_df <- data.frame(a=1, b=2)
        return_df <- cbind(return_df,small_df)
    }
    
    if (diff_option) {
        #do a bunch of calculations, produce a data.frame, for simplicity the following small2_df
        small2_df <- data.frame(l="hi there", m=44)
        return_df <- cbind(return_df,small2_df)
    }
    
    return_df
    

    Understandably, this produces an error:

    Error in data.frame(..., check.names = FALSE) : 
    arguments imply differing number of rows: 0, 1
    

    My current fix is to replace the line return_df <- data.frame() with return_df <- data.frame(dummy=1) and then the code works. I then just remove dummy from the return_df at the end. After adding the dummy and running the above code, I get

          dummy a b        l  m
    1     1 1 2 hi there 44
    

    I then just need to get rid of the dummy, e.g.:

    > return_df[,2:ncol(return_df)]
      a b        l  m
    1 1 2 hi there 44
    

    I'm sure I'm missing an easier way to do this.

    edit: I guess I'm not looking for a cbind.fill because that would mean that an NA value would be created after the cbind, which is not what I want.

  • Xu Wang
    Xu Wang over 12 years
    Thanks Tyler. But I have a data frame and not a matrix, and I think that does disrupt this implementation. Also, I've edited my post because I think I was mistaken -- I don't think I want a cbind.fill, because that would create an NA, whereas I want nothing created.
  • Tyler Rinker
    Tyler Rinker over 12 years
    I edited my post to make the code work on both dataframes and matrices. I don't think it's possible to output a dataframe of unequal rows. By definition a dataframe is a list of equal length n's, so a dataframe not in a rectangular shape would not be possible.
  • Max
    Max over 12 years
    @Xu Wang, there are functions as.data.frame() and as.matrix(), so it is not problem that you have data.frame and not matrix.
  • Xu Wang
    Xu Wang over 12 years
    Thanks Max! I like your solution. I will point out (for future readers) that this solution requires loading the package plyr, where Tyler's does not depend on any extra packages (I think).
  • Max
    Max over 12 years
    @Xu Wang, added require(plyr) statement.
  • Tyler Rinker
    Tyler Rinker over 12 years
    One note is that Max's solution returns a data frame where as mine returns a matrix. If you really wanted the function to return a matrix you could wrap the last line with as.data.frame()
  • MERose
    MERose about 9 years
    Just a quick sitenote: The code is also available on Gist.
  • christopherlovell
    christopherlovell about 9 years
    the function cbind.na no longer appears to be a part of the package qpcR
  • lauren.marietta
    lauren.marietta over 4 years
    Looks like rowr was deprecated?