rloopsrenamecbindr-colnames

How to name a column using cbind, in a loop


I am using a loop to rename columns using cbind. Every time I attempt to name the column using the loop indices (i), it does not use the indices and instead puts in i for the column names. I want it to display the actual names from the original

x <- seq(0, 50, by = 1)
y <- seq(50, 100, by = 1)
z <- seq(25, 75, by = 1)

df <- data.frame(cbind(x, y, z))

df_final <- NULL
for (i in colnames(df)){

#PROBLEM: Column names becomes i instead of the actual column names
df_final <- cbind(df_final, i = df[,i])

}
df_final

Solution

  • A simple solution will be to set the colname in the loop like:

    df_final <- NULL
    for (i in colnames(df)){
      df_final <- cbind(df_final, df[,i])
      colnames(df_final)[ncol(df_final)]  <- i
    }
    colnames(df_final)
    #[1] "x" "y" "z"
    str(df_final)
    # num [1:51, 1:3] 0 1 2 3 4 5 6 7 8 9 ...
    # - attr(*, "dimnames")=List of 2
    #  ..$ : NULL
    #  ..$ : chr [1:3] "x" "y" "z"
    

    For using the method x[[i]] <- value, x need to have rows:

    df_final <- data.frame()[seq_len(nrow(df)),0] #Create empty data frame with rows
    for (i in colnames(df)){
      df_final[[i]] <- df[,i]
    }
    colnames(df_final)
    #[1] "x" "y" "z"
    str(df_final)
    #'data.frame':   51 obs. of  3 variables:
    # $ x: num  0 1 2 3 4 5 6 7 8 9 ...
    # $ y: num  50 51 52 53 54 55 56 57 58 59 ...
    # $ z: num  25 26 27 28 29 30 31 32 33 34 ...
    

    otherwise it will create a list, which could be converted to a data.frame with list2DF.

    df_final <- NULL
    for (i in colnames(df)){
      df_final[[i]] <- df[,i]
    }
    colnames(df_final)
    #NULL
    str(df_final)
    #List of 3
    # $ x: num [1:51] 0 1 2 3 4 5 6 7 8 9 ...
    # $ y: num [1:51] 50 51 52 53 54 55 56 57 58 59 ...
    # $ z: num [1:51] 25 26 27 28 29 30 31 32 33 34 ...
    
    df_final  <- list2DF(df_final)
    
    colnames(df_final)
    #[1] "x" "y" "z"
    str(df_final)
    #'data.frame':   51 obs. of  3 variables:
    # $ x: num  0 1 2 3 4 5 6 7 8 9 ...
    # $ y: num  50 51 52 53 54 55 56 57 58 59 ...
    # $ z: num  25 26 27 28 29 30 31 32 33 34 ...
    

    When the loop is done with sapply instead of for a solution would be:

    df_final <- sapply(colnames(df), function(i) {df[,i]})
    colnames(df_final)
    #[1] "x" "y" "z"
    str(df_final)
    # num [1:51, 1:3] 0 1 2 3 4 5 6 7 8 9 ...
    # - attr(*, "dimnames")=List of 2
    #  ..$ : NULL
    #  ..$ : chr [1:3] "x" "y" "z"
    
    as.data.frame.matrix(df_final)  # Convert it to data.frame
    

    Or simply subsetting:

    df_final <- df[colnames(df)]
    colnames(df_final)
    #[1] "x" "y" "z"
    str(df_final)
    #'data.frame':   51 obs. of  3 variables:
    # $ x: num  0 1 2 3 4 5 6 7 8 9 ...
    # $ y: num  50 51 52 53 54 55 56 57 58 59 ...
    # $ z: num  25 26 27 28 29 30 31 32 33 34 ...