R function using . and ~

淺唱寂寞╮ 提交于 2019-12-22 13:04:56

问题


I'm trying to learn to use ~ and . in R.

In the code below is the same function written with and without the use of ~ and ..I didn't understand what happened in the first function to appear the error.

#FIRST FUNCTION
col_summary2 <- function(.x, .f, ...){
  .x <- purrr::keep(.x, is.numeric)
  purrr::map_dbl(.x, ~.f(., ...))
}

col_summary2(mtcars,mean) #Error in mean.default(., ...) : 'trim' must be numeric of length one

#SECOND FUNCTION
col_summary2 <- function(.x, .f, ...){
  .x <- purrr::keep(.x, is.numeric)
  purrr::map_dbl(.x, function(x) .f(x, ...))
}

col_summary2(mtcars,mean) #mpg        cyl       disp         hp       drat         wt       qsec         vs      am       gear       carb
                          #20.090625   6.187500 230.721875 146.687500   3.596563   3.217250  17.848750   0.437500 0.406250   3.687500   2.812500 

回答1:


In the first case your argument is passed to purrr::as_mapper internally:

as_mapper(~f(., ...))
# function (..., .x = ..1, .y = ..2, . = ..1) 
#   f(., ...)

Which means it behaves just as if you had written :

purrr::map_dbl(.x, function(..., .x = ..1, .y = ..2, . = ..1) f(., ...))

The function that is created has a ... argument, (it always has, it would even if .f didn't have it).

The .x, .y, and . arguments are actually extracted from the ..., as ..1 means "first thing stuffed into ...", ..2 means "second thing..." and so on.

So in your first case .x is passed through ... and ends up in . as well.

col_summary3 <- function(.x, .f, ...){
  .x <- purrr::keep(.x, is.numeric)
  purrr::map_dbl(.x, ~{print(list(...));.f(., ...)})
}
col_summary3(mtcars,mean) 
# [[1]]
# [1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4 10.4
# [17] 14.7 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4 15.8 19.7 15.0 21.4
#  Error in mean.default(., ...) : 'trim' must be numeric of length one 

.x ends up being fed both to the first argument of .f and to the second through .f(.,...), so it ends up in the second argument of mean.default, i.e. trim, which doesn't like it.

It's not the case in your second function, where the ... argument (not used in this case) is smoothly passed from the initial call to the .f call.

Re "So, in this case, I can't use ~ and ., right?"

You can't use it directly as there is a conflict with .... You can go around it however by passing it to the .y argument and use purr::invoke, but that's very mean for the next person that will have to read it :).

col_summary4 <- function(.x, .f, ...){
  .x <- purrr::keep(.x, is.numeric)
  purrr::map_dbl(.x, ~ invoke(.f, .y, .), .y=list(...))
}

col_summary4(mtcars,mean) 
# mpg        cyl       disp         hp       drat         wt       qsec         vs         am       gear       carb 
# 20.090625   6.187500 230.721875 146.687500   3.596563   3.217250  17.848750   0.437500   0.406250   3.687500   2.812500 

col_summary4(mtcars,mean, trim = 0.3)
# mpg         cyl        disp          hp        drat          wt        qsec          vs          am        gear        carb 
# 19.1785714   6.4285714 214.5071429 136.2857143   3.5971429   3.2467857  17.7600000   0.3571429   0.2857143   3.5714286   2.6428571 


来源:https://stackoverflow.com/questions/51362474/r-function-using-and

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!