Home > Net >  rename a column based on the original column's name R
rename a column based on the original column's name R

Time:10-04

I have a dataframe that similar to this: (in fact, 16 in a for-loop)

head(data)
# A tibble: 1 x 4
    AAA   AAC    AB    AC
1    18    25    39     9
2    20    25    30     7
  • I want to dinamically change all collumns names based on the columns' original names, something like this (I've tried with str_glue, but I get an error):
### I have a for-loop: (NOT WORKING) (this is a part of the loop)

assign(str_glue("df_{str_sub(data[i], 23, - 5)}"),
           read.delim(data[i], sep = ",", header = T) %>% 
             mutate(ID = Participants,
             str_glue("New_{str_sub(data[i], 23, - 5)}_AAA") = AAA,
             str_glue("New_{str_sub(data[i], 23, - 5)}_AAB") = AAC,
             str_glue("New_{str_sub(data[i], 23, - 5)}_AB") = AB,
             str_glue("New_{str_sub(data[i], 23, - 5)}_AC") = AC) 
  • desired output:
### Note:
### depending on the index-i, 
### str_glue("New_{str_sub(data[i], 23, - 5)}_AAA") will get me either 50,100 or 150

### desired output for i = 1 
    New_50_AAA   New_50_AAC    New_50_AB    New_50_AC
1    18    25    39     9
2    20    25    30     7
  • I'm sure that there's an elegant way to do that. I've seen some related posts, but none seemed to help me. Any ideas? Thanks :)

  • ps: If there's also a way to dinamically repeat the original's column name without repeating it with str_, that would be perfect, it would save me 4 lines

  • EDIT

The whole loop looks like this:

"data" is a list of 16 .txt files, each one is called "xxxxxxxxx_xx_50.txt", "xxxxxxxxx_xx_100.txt" (so on)

for (i in 1:length(data)) {
  
  if (grepl("xxxxxxxxx_x1_.txt$", data[i])) {
    
    assign(str_glue("df_narr{str_sub(data[i], 23, - 5)}"),
           read.delim(data[i], sep = ",", header = T) %>% 
           mutate(ID = Participants,
             str_glue("New_1{str_sub(data[i], 23, - 5)}_AAA") = AAA,
             str_glue("New_1{str_sub(data[i], 23, - 5)}_AAB") = AAC,
             str_glue("New_1{str_sub(data[i], 23, - 5)}_AB") = AB,
             str_glue("New_1{str_sub(data[i], 23, - 5)}_AC") = AC) %>%
             mutate_if(is.numeric, round, digits = 2)) 

} else if (grepl("xxxxxxxxx_x2_.txt$", data[i])) {

assign(str_glue("df_narr{str_sub(data[i], 23, - 5)}"),
           read.delim(data[i], sep = ",", header = T) %>% 
           mutate(ID = Participants,
             str_glue("New_2{str_sub(data[i], 23, - 5)}_AAA") = AAA,
             str_glue("New_2{str_sub(data[i], 23, - 5)}_AAB") = AAC,
             str_glue("New_2{str_sub(data[i], 23, - 5)}_AB") = AB,
             str_glue("New_2{str_sub(data[i], 23, - 5)}_AC") = AC) %>%
             mutate_if(is.numeric, round, digits = 2)) 
  }
}

CodePudding user response:

It is better to keep the datasets in a list and rename them - get the files in the folder with list.files, then extract the digits (\\d - one or more digits) before the .txt from the files ('nm1'), loop over the files and the names extracted in Map, read the data and modify the column names by pasteing the 'New_', corresponding digits ('nm') and the original column names

files <- list.files(path = 'path/to/your/folder', pattern = "\\.txt$", 
     full.names = TRUE)
nm1 <- sub(".*_(\\d )\\.txt", "\\1", basename(files))
lst1 <- Map(\(x, nm) {

        tmp <- read.table(x) 
        num_cols <- sapply(tmp, is.numeric)
        tmp[num_cols] <- lapply(tmp[num_cols], round, digits = 2)
        cols_to_rename <- names(tmp) != "Participants"
         names(tmp)[cols_to_rename] <- paste0("New_", nm, "_", 
               names(tmp)[cols_to_rename])
         names(tmp)[!cols_to_rename] <- "ID"
        tmp
    }, files, nm1)

Or using tidyverse

library(dplyr)
library(readr)
library(purrr)
library(stringr)
lst2 <- imap(setNames(files, nm1), ~ {
      nm <- .y
      read_table(.x) %>%
       rename_with(~ str_c("New_", nm, "_", .x), -Participants) %>%
      mutate(across(where(is.numeric), round, digits = 2)) %>%
      rename(ID = Participants)
    })

or in a for loop

# for storing the output from the `for` loop
lst3 <- vector('list', length(files))
# loop over the sequence of files
for(i in seq_along(files)) {
   tmp <- read.table(files[i])
   cols_to_rename <- names(tmp) != "Participants"
    names(tmp)[cols_to_rename] <- paste0("New_", nm1[i], "_", 
               names(tmp)[cols_to_rename]) 
    names(tmp)[!cols_to_rename] <- "ID"
   num_cols <- sapply(tmp, is.numeric)
   tmp[num_cols] <- lapply(tmp[num_cols], round, digits = 2)
   lst3[[i]] <- tmp
  }
  • Related