Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using dplyr mutate_at with custom function

Tags:

r

dplyr

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)))
like image 229
ZRoss Avatar asked Apr 10 '18 16:04

ZRoss


1 Answers

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:

  1. If you need the function to reference a grouping variable, use cur_data_all()
  2. mutate_at is now superseded by mutate(.data, across()), so it would be better to do
mtcars %>% mutate(across(.cols=c(mpg, cyl), .fns=f, .names='{.col}_xyz'))
like image 92
randy Avatar answered Sep 18 '22 22:09

randy