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...
CodePudding user response:
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
CodePudding user response:
We need to use deparse/substitute
at the start of the function
rename_fun <- function(x) {
y <- deparse(substitute(x))
colnames(x)[1] <- "___0"
colnames(x)[2] <- "___1"
assign(y, x, envir = .GlobalEnv)
}
-testing
> rename_fun(df)
> df
___0 ___1
1 1 Rick
2 2 Dan
3 3 Michelle
4 4 Ryan
5 5 Gary