Search code examples
rfunctionassign

How to get the object name as a string inside a function in r


I want to change column names of a data frame with a function.

To overwrite my data frame with the new column names, I used assign(), which first argument has to be the name of the same data frame as a string. To get the name as a string, I used deparse(substitute(x)), which worked outside the function. But inside the function, it returns the content of my data frame as a string instead of the name itself...


df <- data.frame(
  emp_id = c (1:5), 
  emp_name = c("Rick","Dan","Michelle","Ryan","Gary"),
  stringsAsFactors = FALSE
)

deparse(substitute(df))

rename_fun <- function(x) {
  colnames(x)[1] <- "___0"
  colnames(x)[2] <- "___1"

  y <- deparse(substitute(x))
  
    assign(y, x, envir = .GlobalEnv)      
}

rename_fun(df)

I also tried

as.character(substitute(x))

but the same problem...


Solution

  • An alternative is to use as.character(match.call()$x), which can be used at any point in the function:

    rename_fun <- function(x) {
      colnames(x)[1] <- "___0"
      colnames(x)[2] <- "___1"
      assign(as.character(match.call()$x), x, envir = .GlobalEnv)      
    }
    

    Giving

    rename_fun(df)
    
    df
    #>   ___0     ___1
    #> 1    1     Rick
    #> 2    2      Dan
    #> 3    3 Michelle
    #> 4    4     Ryan
    #> 5    5     Gary
    

    Note though that functions which write objects into the global environment as a side effect are not recommended, even if they are overwriting an existing object. A function should return the altered data frame, which the user may then choose to use to overwrite the object.

    A better way to write the function would be:

    rename_fun <- function(x) {
      
      colnames(x)[1] <- "___0"
      colnames(x)[2] <- "___1"
      x
    }
    

    Which would be called like this:

    df <- rename_fun(df)
    

    And give the same result, while leaving the option of having a copy of the original data frame if the caller wants.

    Created on 2022-11-18 with reprex v2.0.2