0

My data looks as follows:

DT1 <- structure(list(Province = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 
2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3), Year = c(2000, 
2000, 2000, 2001, 2001, 2001, 2002, 2002, 2002, 2000, 2000, 2000, 
2001, 2001, 2001, 2002, 2002, 2002, 2000, 2000, 2000, 2001, 2001, 
2001, 2002, 2002, 2002), Municipality = c("Something", "Anything", 
"Nothing", "Something", "Anything", "Nothing", "Something", "Anything", 
"Nothing", "Something", "Anything", "Nothing", "Something", "Anything", 
"Nothing", "Something", "Anything", "Nothing", "Something", "Anything", 
"Nothing", "Something", "Anything", "Nothing", "Something", "Anything", 
"Nothing"), Values = c(0.59, 0.58, 0.66, 0.53, 0.94, 0.2, 0.86, 
0.85, 0.99, 0.59, 0.58, 0.66, 0.53, 0.94, 0.2, 0.86, 0.85, 0.99, 
0.59, 0.58, 0.66, 0.53, 0.94, 0.2, 0.86, 0.85, 0.99)), row.names = c(NA, 
-27L), class = c("tbl_df", "tbl", "data.frame"))
DT1_list <- DT1%>%
  group_split(Province, Year)

I want to rename all the columns, using a vector as follows:

colnames <- c("newname1","newname2","newname3","newname4")

for (i in DT1_list) {
    names(DT1_list)[[i]] <- colnames
    }

The problem is that names(DT1_list)[[i]] does not give column names but NULL.

What is the correct way to do this?

EDIT:

I noticed that my question, was not a good enough representation of my actual problem (my apologies, I did not foresee the the issue). My actual problem is that I want to rename 3 out of 4 columns:

colnames <- c("newname1","newname2","newname3")

If I use the answers provided, the fourth column becomes NA. Is there anyway to keep the other columns intact?

aynber
  • 22,380
  • 8
  • 50
  • 63
Tom
  • 2,173
  • 1
  • 17
  • 44

2 Answers2

3

You could use purrr:map:

library(purrr)                                                                                                                                                              0.59, 0.58, 0.66, 0.53, 0.94, 0.2, 0.86, 0.85, 0.99)), row.names = c(NA, 
                                                                                                                                                                                                                                   -27L), class = c("tbl_df", "tbl", "data.frame"))
DT1_list <- DT1%>%
  group_split(Province, Year)

library(purrr)                                                                                                                                                              0.59, 0.58, 0.66, 0.53, 0.94, 0.2, 0.86, 0.85, 0.99)), row.names = c(NA, 
                                                                                                                                                                                                                                   -27L), class = c("tbl_df", "tbl", "data.frame"))
DT1_list <- DT1%>%
  group_split(Province, Year)

DT1_list %>% map(~{colnames <- colnames(.x)
                   #You could also use str_replace
                   #colnames <- stringr::str_replace(colnames,"Values","NewValues")
                   colnames[1:3] <- c("newname1","newname2","newname3")
                   colnames(.x)<- colnames
                   .x})

[[1]]
# A tibble: 3 x 4
  newname1 newname2 newname3  Values
     <dbl>    <dbl> <chr>      <dbl>
1        1     2000 Something  0.59 
2        1     2000 Anything   0.580
3        1     2000 Nothing    0.66 

[[2]]
# A tibble: 3 x 4
  newname1 newname2 newname3  Values
     <dbl>    <dbl> <chr>      <dbl>
1        1     2001 Something   0.53
2        1     2001 Anything    0.94
3        1     2001 Nothing     0.2 

...
Waldi
  • 39,242
  • 6
  • 30
  • 78
  • Thank you for your answer. I have a small question. I noticed in my actual data that if I do not rename all columns, the names of the columns I do not rename become `NA`. That is an issue because I wanted to refer to those columns by name. Is is possible to stop that from happening? Say for example I want to rename only 3 columns. – Tom Mar 14 '21 at 08:14
  • 1
    Thank you very much! I went for the other answer for not requiring a library. – Tom Mar 14 '21 at 08:50
  • @Tom, fair enough! – Waldi Mar 14 '21 at 08:55
2

You can use lapply/map :

lapply(DT1_list, setNames, colnames)

#[[1]]
# A tibble: 3 x 4
#  newname1 newname2 newname3  newname4
#     <dbl>    <dbl> <chr>        <dbl>
#1        1     2000 Something    0.59 
#2        1     2000 Anything     0.580
#3        1     2000 Nothing      0.66 

#[[2]]
# A tibble: 3 x 4
#  newname1 newname2 newname3  newname4
#     <dbl>    <dbl> <chr>        <dbl>
#1        1     2001 Something     0.53
#2        1     2001 Anything      0.94
#3        1     2001 Nothing       0.2 
#...
#...

When you want to rename less columns than your original data use :

inds <- seq_along(colnames)
lapply(DT1_list, function(x) {names(x)[inds] <- colnames;x})

Or :

library(dplyr)
library(purrr)

map(DT1_list, ~.x %>% rename_with(~colnames, inds))
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • Thank you for your answer! The splitting was done just to recreate data similar to the data that I have (I did not split up the original data, it comes split up). – Tom Mar 14 '21 at 08:10
  • I have a small question. I noticed in my actual data that if I do not rename all columns, the names of the columns I do not rename become `NA`. That is an issue because I wanted to refer to those columns by name. Is is possible to stop that from happening? Say for example I want to rename only 3 columns. – Tom Mar 14 '21 at 08:14
  • See the updated answer for handling such cases. – Ronak Shah Mar 14 '21 at 08:20