I'm sorry for the confusion but eventually, the first example I posted (at the bottom of the page), did not help me to figure out how tidyeval works with mutate, so I'm adding a new example.
I would like to create a function that takes three args:
- a dataframe
- the column(s) to mutate
- a variable (from the dataframe) to replace the values that are being mutated
For instance, to replace the values in mpg
with the values from carb
I tried this:
I tried this
colToX <- function(dt, ..., repl) {
cols <- quos(...)
repl <- quo(repl)
mutate_at(dt, vars(!!!cols), funs(function(x) !!repl))
}
colToX(mtcars, mpg, repl = carb)
which doesn't work since:
Error in mutate_impl(.data, dots) : Column
mpg
is of unsupported type function
My first example (@MrFlick's and @UseR's both work fine for this):
For instance, the one below should mutate()
assigning all 1 to the variable passed in ...
colTo1 <- function(dt, ...) {
col <- quo(...)
mutate(mtcars, !!col := 1)
}
colTo1(mtcars, mpg)
Error: LHS must be a name or string
Eventually, the output should be the same as mutate(mtcars, mpg = 1)
As the error says "Error: LHS must be a name or string" where LHS means left-hand side and it's specifically referring to the
!!col := 1
part. You need to turn the quosure you made into a string or symbol. It's probably easiest to get the string version of the quosure withquo_name
@MrFlick's solution works for the one column case, but since OP used
...
as an argument, I assume OP would also want the function to be able to take in multiple columns. For example, the following would not work:What we can do is to use
quos
instead ofquo
andmutate_at
instead ofmutate
:quos
converts each argument from...
into vector of quosures. Usingmutate_at
'svars
syntax and explicit splicing with!!!
fromrlang
, we can unquote each quosure incols
, and mutate on those specified columns.Now this works as intended:
Result:
It's also easy enough to let "
1
" be another argument to be passed into the function:Edit: OP changed the question to require that
X
should be another column in the same dataframe. Below is my new solution:Here, I am using the
funs
function to create a list of function calls to each column referenced fromvars
..data
refers to the input dataframe intomutate_at
(in this casedt
). I usedenquo
to convert what's called fromX
into a quosure and unquote it using!!
.Result: