rcbind

cbind with empty objects for looping iteration


I would like to do a cbind with two data.frame objects. However the first one is empty, just created for loop iteration. I would like to know if it is possible.

When I try:

data <- data.frame()

data1 <- cbind(data, mpg)

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

I am not successful.

My loop is a little longer, but in general, I have about 100 files in which I need to create the taxa_col_name variable and I need to add the data.frame generated in the loop to a data.frame that will be my final base.

data <- data.frame()
    
for (i in 1:100) {
rate_col_name <- sprintf("rate_%s", i)
data1 <- data1 %>%
mutate(!!rate_col_name:=
       (population_2000)*((population_2010/population_2000_previous)))
       data1$population_2010 = NULL
       data1$population_2000_previous <- NULL
       rm(pop_2000_previous, pop_2010)
       gc()
date <- cbind(date, date1)
}

Solution

  • This happens when you attempt to cbind the existing but empty data with data1, which actually has rows and presumably one column. That's because for cbind, the two data frames need to have the same nunmber of rows. A minimum example to produce that error is:

    > data <- data.frame()
    > data_input <- data.frame(mydata=1:10)
    > cbind(data, data1)
    Error in data.frame(..., check.names = FALSE) : 
      arguments imply differing number of rows: 0, 10
    

    For you, this is happening at the end of the first iteration of your loop. Here's a shorter version of that:

    > data_input <- rnorm(n = 10)
    > data <- data.frame()
    > for (i in 1:10) {
    +   message("I'm in iteration ", i)
    +   data1 <- data_input + i 
    +   data <- cbind(data, data1)
    + }
    I'm in iteration 1
    Error in data.frame(..., check.names = FALSE) : 
      arguments imply differing number of rows: 0, 10
    

    One solution is to initialize data with actual data in the first iteration of the loop:

    data_input <- seq(from=100, to=1000, by=100)
    for (i in 1:10) {
      data1 <- data_input + i
      if(i==1){
        data <- data.frame(data1)
      }else{
        data <- cbind(data, data1)
      }
    }
    

    One could also do the first iteration "manually" outside the loop and then start the loop at 2 instead of 1:

    data_input <- seq(from=100, to=1000, by=100)
    data1 <- data_input + 1
    data <- data.frame(data1)
    for (i in 2:10) {
      data1 <- data_input + i
      data <- cbind(data, data1)
    }
    

    Another solution is to start with a list and turn that into a data.frame in the end:

    data_input <- seq(from=100, to=1000, by=100)
    data <- list()
    for (i in 1:10){
      data1 <- data_input + i
      data[[i]] <- data1
    }
    data <- data.frame(do.call('cbind', data))