30
votes

dplyr's rename functions require the new column name to be passed in as unquoted variable names. However I have a function where the column name is constructed by pasting a string onto an argument passed in and so is a character string.

For example say I had this function

myFunc <- function(df, col){
  new <- paste0(col, '_1')
  out <- dplyr::rename(df, new = old)
  return(out)
}

If I run this

df <- data.frame(a = 1:3, old = 4:6)
myFunc(df, 'x')

I get

  a new
1 1   4
2 2   5
3 3   6

Whereas I want the 'new' column to be the name of the string I constructed ('x_1'), i.e.

  a x_1
1 1   4
2 2   5
3 3   6

Is there anyway of doing this?

2
From the announcement of dplyr 0.3: "You can now program with dplyr – every function that uses non-standard evaluation (NSE) also has a standard evaluation (SE) twin that ends in _ [...] The SE version of each function has similar arguments, but they must be explicitly “quoted”." Thus, check if rename_ might be useful here. - Henrik
Thanks, that is useful to know but it doesn't actually change anything in this case. It would work if the column I was passing in was the old column name, but changing the above function to use rename_ (and putting old in quotes) still returns the same - user1165199
@user1165199 I would do colnames(df)[colnames(df) %in% "old"] <- paste0("x","_") (in a function if that is necessary) as it is able to replace a vector of names easily. - akrun
Thanks akrun, that is what I have done in the end. Was just hoping there was a neater way of doing it using an existing function. - user1165199
I want to send a concatenated list to all the column names. df <%>` new <- c("a.new", "b.new") %>% names(.) <- rename_(new) - mtelesha

2 Answers

23
votes

I think this is what you were looking for. It is the use of rename_ as @Henrik suggested, but the argument has an, lets say, interesting, name:

> myFunc <- function(df, col){
+   new <- paste0(col, '_1')
+   out <- dplyr::rename_(df, .dots=setNames(list(col), new))
+   return(out)
+ }
> myFunc(data.frame(x=c(1,2,3)), "x")
  x_1
1   1
2   2
3   3
>

Note the use of setNames to use the value of new as name in the list.

1
votes

Recent updates to tidyr and dplyr allow you to use the rename_with function.

Say you have a data frame:

library(tidyverse)

df <- tibble(V0 = runif(10), V1 = runif(10), V2 = runif(10), key=letters[1:10])

And you want to change all of the "V" columns. Usually, my reference for columns like this comes from a json file, which in R is a labeled list. e.g.,

colmapping <- c("newcol1", "newcol2", "newcol3")
names(colmapping) <- paste0("V",0:2)

You can then use the following to change the names of df to the strings in the colmapping list:

df <- rename_with(.data = df, .cols = starts_with("V"), .fn = function(x){colmapping[x]})