5

I am having difficulty renaming columns in a function using dplyr. I have already found helpful posts on nonstandard evaluation and the use of enquo (e.g., http://dplyr.tidyverse.org/articles/programming.html and Changing names of resulting variables in custom dplyr function). The ultimate goal is to use the function to summarise each group, and then rename the columns into something more meaningful than the original variable names.

Here is a simple example, which works except for the commented-out lines.

library(tidyverse)

myfunc <- function(df, groupvar, colvar, grouplab, collab) {
  groupvar <- enquo(groupvar)
  colvar <- enquo(colvar)
  grouplab <- enquo(grouplab)  # quo_name instead?
  collab <- enquo(collab)  # quo_name instead?

t <- df %>%
  select(!!groupvar, !!colvar) %>%
  group_by(!!groupvar, !!colvar) %>%
  summarise(
    Frequencies = length(!!colvar),
    Percentages = length(!!colvar) / nrow(df)
    ) %>%
  mutate(
    Frequencies = scales::comma(Frequencies),
    Percentages = scales::percent(Percentages)
    ) #%>%
# rename(
#    (!!grouplab) = !!groupvar,  # add a more descriptive grouping var label
#    (!!collab) = !!colvar)  # add a more descriptive column var label

# Error: unexpected '=' in: rename((!!grouplab) = "

...  # code to create an xtable, print it into LaTeX
}

myfunc <- (df = mtcars, groupvar = gear, colvar = cyl, grouplab = "Vehicle Gears", collab = "Vehicle Cylinders")
# I purposely made grouplab and collab have a space in case that changes anything. 

Outside of functions, the relevant part would read simply: mtcars <- mtcars %>% rename("Vehicle Cylinders" = cyl, "Vehicle Gears" = gear)

I must be getting tripped up in how renaming operates in a function vs. outside of it. Any advice? I'm open to suggestions.

UPDATE
Here is one way to do it. I'd rather not put the variable names in strings, but don't know a way around it here. Open to suggestions.

library(tidyverse)
library(xtable)
data(mtcars)

t_groupedfreqprop <- function(df, groupvar, colvar, grouplab, collab, plotname) {
groupvar2 <- rlang::sym(groupvar)
colvar2 <- rlang::sym(colvar)
grouplab <- rlang::sym(grouplab)
collab <- rlang::sym(collab)

t <- df %>%
  select(!!groupvar2, !!colvar2) %>%
  group_by(!!groupvar2, !!colvar2) %>%
  summarise(
    Frequencies = length(!!colvar2),
    Percentages = length(!!colvar2) / nrow(df)
  ) %>%
  mutate(
    Frequencies = scales::comma(Frequencies),
    Percentages = scales::percent(Percentages)
  ) %>%
  rename(
    !!grouplab := !!rlang::sym(groupvar2),
    !!collab := !!rlang::sym(colvar2)
  )

# remainder of function removed
}

t_groupedfreqprop(df = mtcars, groupvar = "gear", colvar = "cyl", grouplab = "Vehicle Gears", collab = "Vehicle Cylinders")
Daniel
  • 415
  • 1
  • 6
  • 16

2 Answers2

11

Use := if you want programmatically-assigned names on the LHS of expressions.

x <- "mpg"
xnew <- "mpg2"
rename(mtcars, !!xnew := !!rlang::sym(x))
Hong Ooi
  • 56,353
  • 13
  • 134
  • 187
  • Thanks, @Hong Ooi. Does this technique still work in a function - i.e., where I'm not hard-coding the new names? – Daniel Aug 11 '17 at 23:19
  • Yes it should work but you have to use `enquo` for quoting `x` and `xnew` then you can Unquote. See the programming vignette in `dplyr` for more information in *tidyeval* concept. – cderv Aug 12 '17 at 06:06
  • Thanks. I must still be missing something... Boiling down the function to the relevant part throws an error: "Error: Only strings can be converted to symbols." This vignette helps (https://cran.r-project.org/web/packages/rlang/vignettes/tidy-evaluation.html), but I'm still struggling with how to work inside a function. t_groupedfreqprop <- function(df, groupvar, grouplab) { groupvar <- enquo(groupvar) grouplab <- enquo(grouplab) t <- df %>% rename( !!grouplab := !!rlang::sym(groupvar)) } t_groupedfreqprop(df = mtcars, groupvar = gear, grouplab = "Vehicle Gears") – Daniel Aug 12 '17 at 17:00
6

To rename multiple columns at once, you have to use !!!:

x <- c("mpg", "cyl")
xnew <- paste(x, 2, sep = ".")
names(x) <- xnew
rename(mtcars, !!!x)
caewok
  • 91
  • 1
  • 3