I'd like to use mutate function from the tidyverse to create a new column based on the old column using only a data frame and strings, which represent column headers, as inputs.
I can get this to work without using the tidyverse (see function f below), but I'd like to get it to work using the tidyverse (see function f.tidy below)
Can someone please post a solution for adding this column using mutate called from a inside function?
df <- data.frame('test' = 1:3, 'tcy' = 4:6)
# test tcy
# 1 4
# 2 5
# 3 6
f.tidy <- function(df, old.col, new.col) {
df.rv <- df %>%
mutate(new.col = .data$old.col + 1)
return(df.rv)
}
f <- function(df, old.col, new.col) {
df.rv <- df
df.rv[, new.col] <- df.rv[, old.col] + 1
return(df.rv)
}
old.col <- 'tcy'
new.col <- 'dan'
f.tidy(df = df, old.col = old.col, new.col = new.col)
# Evaluation error: Column 'old.col': not found in data
f(df = df, old.col = old.col, new.col = new.col)
# Produces Desired Output:
# test tcy dan
# 1 4 5
# 2 5 6
# 3 6 7
The dplyr library has the following functions that can be used to add additional variables to a data frame. mutate() – adds new variables while retaining old variables to a data frame. transmute() – adds new variables and removes old ones from a data frame.
dplyr functions use non-standard evaluation. That is why you do not have to quote your variable names when you do something like select(mtcars, mpg) , and why select(mtcars, "mpg") doesn't work. When you use dplyr in functions, you will likely want to use "standard evaluation".
mutate() adds new variables and preserves existing ones; transmute() adds new variables and drops existing ones. New variables overwrite existing variables of the same name. Variables can be removed by setting their value to NULL .
To use mutate in R, all you need to do is call the function, specify the dataframe, and specify the name-value pair for the new variable you want to create.
We could use rlang
to convert it to symbol and then evaluate with !!
f.tidy <- function(df, old.col, new.col) {
df %>%
mutate(!! (new.col) := !!rlang::sym(old.col) + 1)
}
f.tidy(df = df, old.col = old.col, new.col = new.col)
# test tcy dan
#1 1 4 5
#2 2 5 6
#3 3 6 7
Or another option is mutate_at
with rename_at
f.tidy <- function(df, old.col, new.col) {
df %>%
mutate_at(vars(old.col), funs(new = .+ 1)) %>%
rename_at(vars(matches("new")), ~ new.col)
}
f.tidy(df = df, old.col = old.col, new.col = new.col)
# test tcy dan
#1 1 4 5
#2 2 5 6
#3 3 6 7
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With