51

One can rename a field:

mtcars %>% rename(bla = mpg)

But if the field doesn't exist, an error:

    mtcars %>% rename(MPG = mpg, CYL = cyl, bla = uyhgfrtgf)
Error: Can't rename columns that don't exist.
x Column `uyhgfrtgf` doesn't exist

I looked at ?rename_if and it says this is now superseded by rename_with().

What's the 'right' way to attempt to rename fields but with a possibility they don't exist (e.g. in this case a ShinyApp with filter selectors).

1

5 Answers 5

97

Use any_of() with a named vector. any_of() doesn't error if a variable isn't found.

library(dplyr)

lookup <- c(MPG = "mpg", CYL = "cyl", bla = "uyhgfrtgf")

mtcars %>%
   rename(any_of(lookup))

                   MPG CYL disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
...
Sign up to request clarification or add additional context in comments.

1 Comment

Are you aware of an base R approach as well? If so, could you please refer to?
13

I'm pretty sure you can do this with NSE but I can't handle this (yet?).

So you could define a lookup variable first:

lookup <- c("mpg" = "MPG", "cyl" = "CYL", "uyhgfrtgf" = "bla")

Attention: it's the other way round as in your rename function.

Now you could use

library(dplyr)

df %>% 
  rename_with(.fn = ~lookup[.x], .cols = intersect(names(.), names(lookup)))

which returns

                     MPG CYL  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2

6 Comments

Thanks for this, what's "NSE"? Non standard evaluation?
Yes. Non standard evaluation. Using some curly-curly or big-bang-operators or something like that I don't understand.
Ah I see. Yeah dito, I've found it more tricky to truly grasp NSE in an intuitive way
@DougFir NSE is one of my favorite topics in R you can start from here if you wanna learn more : tidyeval.tidyverse.org/index.html
It's okay. 27 Phi 9's answer is great. 👍🏼
|
12

We could use rename_with from dplyr package and wrap it in a ~case_when function:

library(dplyr)

mtcars %>% 
    rename_with(
        ~ case_when(
        . == "mpg" ~ "MPG",
        . == "cyl" ~ "CYL",
        . == "bla" ~ "uyhgfrtgf",
        TRUE ~ .))

                     MPG CYL  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2

Comments

7

We may use

library(dplyr)
lookup <-c("MPG" = "mpg", "CYL" = "cyl", "bla" = "uyhgfrtgf")
mtcars %>% 
    rename(!!! lookup[names(.) %in% lookup])
                     MPG CYL  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
...

Comments

3

You could use the following solution:

library(dplyr)
library(stringr)

names <- c("mpg", "cyl", "sdad")
reps <- c("MPG", "CYL", "BLA")

mtcars %>%
  rename_with(~ str_replace_all(.x, "\\w+", reps[names(mtcars) %in% names]), matches(names))

                   MPG CYL disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

6 Comments

Nice one! But one hint: you shouldn't name your vector names since this is the name of an actual function.
Yes indeed! however they live in two different environments, mine in global and the other in base so they won't affect one another. But yes you are right.
This is truely right, but some strange structures like names(names) <- names(reps) could occure which are... a bit confusing. ;-)
Yes it's totally not recommended and I was trying so hard to deliver and answer fast :D
You did answer first! :-)
|

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.