Reputation: 1479
I want to take two variables from a table and divide them by a third variable and add these computations as two new columns. The mutate_at
gets me very close but within the custom function, f
below, I want to access another column in the data set. Any suggestions or alternate tidy tools approaches?
library(dplyr)
# this works fine but is NOT what I want
f <- function(fld){
fld/5
}
# This IS what I want where wt is a field in the data
f <- function(fld){
fld/wt
}
mutate_at(mtcars, .vars = vars(mpg, cyl), .funs = funs(xyz = f))
# This works but is pretty clumsy
f <- function(fld, dat) fld/dat$wt
mutate_at(mtcars, .vars = vars(mpg, cyl), .funs = funs(xyz = f(., mtcars)))
# This is closer but still it would be better if the function allowed the dataset to be submitted to the function without restating the name of the dataset
f <- function(fld, second){
fld/second
}
mutate_at(mtcars, .vars = vars(mpg, cyl), .funs = funs(xyz = f(., wt)))
Upvotes: 11
Views: 9426
Reputation: 28705
Updated version for dplyr 1.0.6:
mtcars %>%
mutate(across(c(mpg, cyl), ~ . / wt))
Or this, which may be slower
mtcars %>%
mutate(across(c(mpg, cyl), `/`, wt))
Previous answer:
library(tidyverse)
f <- function(num, denom) num/denom
mtcars %>%
mutate_at(vars(mpg, cyl), f, denom = quote(wt))
Although in this specific example, a custom function isn't needed.
mtcars %>%
mutate_at(vars(mpg, cyl), `/`, quote(wt))
Upvotes: 14
Reputation: 1091
There is a cur_data()
function that will help make the mutate_at()
call more compact because you will not have to specify a second argument to the function that is being applied to each column:
f <- function(fld){
fld / cur_data()$wt
}
mutate_at(mtcars, .vars=vars(mpg, cyl), .funs=funs(xyz = f))
Additional notes:
cur_data_all()
mutate_at
is now superseded by mutate(.data, across())
, so it would be better to domtcars %>% mutate(across(.cols=c(mpg, cyl), .fns=f, .names='{.col}_xyz'))
Upvotes: 1
Reputation: 2551
Maybe something like this?
f <- function(fld,var){
fld/var
}
mtcars %>%
mutate_at(vars(mpg,cyl), .funs = funs(xyz = f(.,wt)))
Edit (2020-08-24):
As of second semester of 2020, with the launch of dplyr 1.0.0, mutate_at
has been superseded by combining mutate
with the across
function:
mtcars %>%
mutate(across(c(mpg, cyl), ~ f(.,wt), .names = "{col}_xyz"))
Upvotes: 11