Reputation: 341
I am mutating a column to create a new one in R using a function I wrote.
Within my function, I want to send a message that includes the name of the column that is being changed.
How can I access the column name that is being mutated from inside of the function within the mutate call?
Reproducible Example:
data <- tribble(
~colB,
1,
2,
3
)
# Function that will be used in the mutate
add1 <- function(numeric_vector) {
return(1 +numeric_vector)
# I want to message the user the name of the column they are mutating
# This simply returns the entire vector
message("You mutated", numeric vector)
# This returns 'numeric_vector'
message("You mutated", quo_name(quo(numeric_vector)))
}
# Desired Output:
data %>%
mutate(colC = add1(colB))
You mutated colB
colB colC
<dbl> <dbl>
1 2
2 3
3 4
Upvotes: 1
Views: 446
Reputation: 269441
Use substitute
which returns a name
class object. We have wrapped the message
call in an on.exit
to ensure that it is run after the calculation so that it is not run if the calculation fails. If that is not important then replace on.exit(message(...))
with just message(...)
. Note that add1
itself does not use any packages.
library(dplyr)
add1 <- function(numeric_vector) {
on.exit(message("You mutated ", substitute(numeric_vector)))
1 + numeric_vector
}
BOD %>% mutate(Time = add1(Time))
giving:
You mutated Time
Time demand
1 2 8.3
2 3 10.3
3 4 19.0
4 5 16.0
5 6 15.6
6 8 19.8
To use rlang make use of enexpr
from that package. dplyr will make it available. enexpr
returns a name
class object.
enexpr
is similar to substitute
but one difference that will affect processing is that substitute
will extract the code portion of a promise whether or not the promise has been forced (i.e. evaluated); however, enexpr
will extract the code of unforced promises but will extract the value of forced promises. Since we want the code portion we must ensure that enexpr(numeric_vector)
is run before numeric_vector
is used in a calculation. To ensure that we introduce a new variable arg_name
which is run at the beginning ensuring that enexpr
has an unforced argument.
library(dplyr)
add2 <- function(numeric_vector) {
arg_name <- enexpr(numeric_vector)
on.exit(message("You mutated ", arg_name))
1 + numeric_vector
}
BOD %>% mutate(Time = add2(Time))
Upvotes: 3
Reputation: 206167
I think you want
add1 <- function(numeric_vector) {
message(paste("You mutated", quo_name(enquo(numeric_vector))))
return(1 + numeric_vector)
}
Note that you have to print your message before the return()
. Nothing after the return()
will run in a function because you exit when you hit that statement. Also, you can use enquo()
to grab the variable to get it's name. And you need to get it's name while it's still in a promise state, so that means before you actually use it's value.
Upvotes: 2