Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rename columns using values from separate dataframe

Tags:

r

dplyr

I have a tibble which has column names containing spaces & special characters which make it a hassle to work with. I want to change these column names to easier to use names while I'm working with the data, and then change them back to the original names at the end for display. Ideally, I want to be able to do this as part of a pipe, however I haven't figured out how to do it with rename_with().

Sample data:

df <- tibble(oldname1 = seq(1:10),
             oldname2 = letters[seq(1:10)],
             oldname3 = LETTERS[seq(1:10)])


cols_lookup <- tibble(old_names = c("oldname4", "oldname2", "oldname1"), 
                      new_names = c("newname4", "newname2", "newname1"))

Desired output:

> head(df_renamed)
# A tibble: 6 x 3
  newname1 newname2 oldname3
     <int> <chr>    <chr>   
1        1 a        A       
2        2 b        B       
3        3 c        C       
4        4 d        D       
5        5 e        E       
6        6 f        F 

Some columns are removed & reordered during this work so when converting them back there will be entries in the cols_lookup table which are no longer in df. There are also new columns created in df which I want to remain named the same.

I am aware there are similar questions which have already been asked, however the answers either don't work well with tibbles or in a pipe (eg. those using match()), or don't work if the columns aren't all present in the same order in both tables.

like image 291
stlba Avatar asked Aug 06 '20 15:08

stlba


2 Answers

We can use rename_at. From the master lookup table, filter the rows where the names of dataset have a match (filtered_lookup), then use that in rename_at where we specify the 'old_names' in vars and replace with the 'new_names'

library(dplyr)
filtered_lookup <- cols_lookup %>% 
     filter(old_names %in% names(df)) 
df %>% 
  rename_at(vars(filtered_lookup$old_names), ~ filtered_lookup$new_names)

Or using rename_with, use the same logic

df %>%
  rename_with(.fn = ~filtered_lookup$new_names, .cols = filtered_lookup$old_names)

Or another option is rename with splicing (!!!) from a named vector

library(tibble)
df %>% 
     rename(!!! deframe(filtered_lookup[2:1]))
like image 180
akrun Avatar answered Oct 02 '22 14:10

akrun


You can use rename_ with setnames

cols_lookup <- tibble(old_names = c("oldname3", "oldname2", "oldname1"), 
                      new_names = c("newname3", "newname2", "newname1"))
df
rename_(df, .dots=setNames(cols_lookup$old_names, cols_lookup$new_names))

Output:

# A tibble: 10 x 3
   newname1 newname2 newname3
      <int> <chr>    <chr>   
 1        1 a        A       
 2        2 b        B       
 3        3 c        C       
 4        4 d        D       
 5        5 e        E       
 6        6 f        F       
 7        7 g        G       
 8        8 h        H       
 9        9 i        I       
10       10 j        J       
like image 28
Arault Avatar answered Oct 02 '22 16:10

Arault