6

I am trying to write a function that will (in part) rename a variable by combining its source dataframe and existing variable name. In essence, I want:

df1 <- data.frame(a = 1, b = 2)

to become:

df1 %>%
  rename(df1_a = a)

#  df1_a b
#1     1 2

But I want to do this programatically, something along the lines of:

fun <- function(df, var) {
  outdf <- rename_(df, paste(df, var, sep = "_") = var)
  return(outdf)
}

This admittedly naive approach obviously doesn't work, but I haven't been able to figure it out. I'm sure the answer is somewhere in the nse vignette (https://cran.r-project.org/web/packages/dplyr/vignettes/nse.html), but that doesn't seem to address constructing variable names.

alexwhan
  • 15,636
  • 5
  • 52
  • 66

2 Answers2

8

Not sure if this is the proper dplyr-esque way, but it'll get you going.

fun <- function(df, var) {
    x <- deparse(substitute(df))
    y <- deparse(substitute(var))
    rename_(df, .dots = with(df, setNames(as.list(y), paste(x, y, sep = "_"))))
}

fun(df1, a)
#   df1_a b
# 1     1 2

fun(df1, b)
#   a df1_b
# 1 1     2
Rich Scriven
  • 97,041
  • 11
  • 181
  • 245
  • 2
    Over in base R land, you could do: `fun <- function(df,var) {names(df)[names(df) %in% var] <- paste(deparse(substitute(df)),var,sep="_"); df}` - which also has the advantage of being vectorized. - `fun(df1, c("a","b"))` – thelatemail Oct 09 '15 at 00:38
  • 1
    Yeah, so far it seems like base R would be easier in this case as this one gets more complicated for multiple columns – Rich Scriven Oct 09 '15 at 00:39
  • You're all correct of course - this was one of those problems that I just couldn't figure out and couldn't let go... – alexwhan Oct 09 '15 at 00:43
0

lazyeval isn't really needed here because the environment of both inputs is known. That being said:

library(lazyeval)
library(dplyr)
library(magrittr)

fun = function(df, var) {
  df_ = lazy(df)
  var_ = lazy(var)
  fun_(df_, var_)
}

fun_ = function(df_, var_) {

  new_var_string = 
    paste(df_ %>% as.character %>% extract(1),
          var_ %>% as.character %>% extract(1), 
          sep = "_")

  dots = list(var_) %>% setNames(new_var_string)

  df_ %>%
    lazy_eval %>%
    rename_(.dots = dots)
}

fun(df1, a)
bramtayl
  • 4,004
  • 2
  • 11
  • 18