bind columns with different number of rows

11,668

Solution 1

Here's one way. The merge function by design will add NA values whenever you combine data frames and no match is found (e.g., if you have fewer values in 1 data frame than the other data frame).

If you assume that you're matching your data frames (what rows go together) based on the row number, just output the row number as a column in your data frames. Then merge on that column. Merge will automatically add the NA values you want and deal with the fact that the data frames have different numbers of rows.

#test data frame 1
a <- c(1, 3, 2)
b <- c(3, 4, 2)
dat <- as.data.frame(cbind(a, b))

#test data frame 2 (this one has fewer rows than the first data frame)
c <- c(5, 6)
dat.new <- as.data.frame(c)

#add column to each data frame with row number
dat$number <- row.names(dat)
dat.new$number <- row.names(dat.new)

#merge data frames
#"all = TRUE" will mean that NA values will be added whenever there is no match 
finaldata <- merge(dat, dat.new, by = "number", all = TRUE)

Solution 2

If you know the maximum possible size of df, and the total number of columns you want to append, you can create df in advance with all NA values and fill a column in based on its length. This would leave everything after its length still NA.

e.g.

max_col_num <- 20 
max_col_size <- 10 #This could be the number of rows in the largest dataframe you have

df <- as.data.frame(matrix(ncol = max_col_num, nrow = max_col_size))

for(i in 1:20){
      temp_seq=another_df$c1[some conditions] 
      df[c(1:length(temp_seq), i] <- temp_seq
}

This would only work if you new the total possible number of rows and columns.

Solution 3

I think the best could be to write a custom function which is based on nrow of data frame and length of vector/list.

Once such function can be written as:

#Function to add vector as column
addToDF <- function(df, v){
 nRow <- nrow(df)
 lngth <- length(v)
 if(nRow > lngth){
   length(v) <- nRow
 }else if(nRow < lngth){
   df[(nRow+1):lngth, ] <- NA
 }
 cbind(df,v)
}

Let's test above function with data.frame provided by OP.

df <- data.frame(A= c(1,3,2), B = c(3, 4, 2))

v <- c(5,6)

w <-c(7,7,8,9)

addToDF(df, v)
#   A B  v
# 1 1 3  5
# 2 3 4  6
# 3 2 2 NA

addToDF(df, w)
#    A  B v
# 1  1  3 7
# 2  3  4 7
# 3  2  2 8
# 4 NA NA 9
Share:
11,668
Cina
Author by

Cina

Updated on June 04, 2022

Comments

  • Cina
    Cina about 2 years

    I want to create iteration that takes a list (which is column of another dataframe) and add it to the current data frame as column. but the length of the columns are not equal. So, I want to generate NA as unmatched rows.

    seq_actions=as.data.frame(x = NA)
    for(i in 1:20){
      temp_seq=another_df$c1[some conditions]  
      seq_actions=cbind(temp_seq,seq_actions)
    }
    

    to simplify, lets say i have

    df
    1  3
    3  4
    2  2
    

    adding the list of 5,6 as new column to df, so I want:

     df
        1  3  5
        3  4  6
        2  2  NA
    

    another adding list is 7 7 7 8, so my df will be:

    df
       1  3  5  7
       3  4  6  7
       2  2  NA 7
       NA NA NA 8
    

    How can I do it?