5

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.

2 Answers 2

6

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]))
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! I'd rather avoid making a separate filtered_lookup table, and have all steps contained within the pipe. A pipe within a pipe with your method works but it's a bit ugly! df %>% rename(!!! deframe((cols_lookup %>% filter(old_names %in% names(df)))[2:1])) As an aside, rename_at has been superseded with rename_with
@stiba for rename to work, it needs all the intersecting columns. If there are names that are not there, it would fail
@stlba you canuse rename_with as well, only thing is that the arguments are reversed
2

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       

1 Comment

That doesn't work with my example data, there is no oldname3/newname3 in my data. rename_() is also deprecated so I'd rather avoid it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.