当我的函数中的数据和变量名称发生变化时,我应该如何编写它们?

时间:2017-09-10 12:43:14

标签: r dplyr

我想使用分位数函数(quantile)创建一个函数,该函数可以在dplyr环境中通过切点生成分位数值。

例如,我想创建一个函数,使结果如下。

# load library and data 
library(dplyr); library(rlang)
iris <- iris 

cut_points_1 <- c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 1) 

quantile(iris$Sepal.Length, cut_points_1)
    0%   10%   20%   30%   40%   50%   60%   70%   80%   90%   95%  100% 
    4.300 4.800 5.000 5.270 5.600 5.800 6.100 6.300 6.520 6.900 7.255 7.900 

但是,我无法理解如何在我的函数中管理这个部分(iris$Sepal.Length)。具体来说,当使用非dplyr函数(例如quantile)时,我不知道如何在data.frame中调用变量名。换句话说,当datavar_name的名称在我的函数中发生变化时,我不知道如何在函数中编写data$var_name

以下是我的代码和功能。

# load library and data 
library(dplyr); library(rlang)
iris <- iris 

# cut-points (percentage)
cut_points_1 <- c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95,     1) 
cut_points_2 <- c(0, 0.2, 0.4, 0.6, 0.8, 1)

# function 
cut <- function(data, var_name, cut_points) {
  data <- enquo(data)
  cut_points <- enquo(cut_points)

  varname_cut <- paste0(substitute(var_name), "_cut") # different variable name: source(https://stackoverflow.com/questions/46131829/unquote-the-variable-name-on-the-right-side-of-mutate-function-in-dplyr/46132317?noredirect=1#comment79234301_46132317)


  !!varname_cut := quantile(!!data$!!var_name, cut_points) # <- This is the problem!
}

# run
cut(iris, Sepal.Length, cut_points_1)
cut(iris, Sepal.Length, cut_points_2)

1 个答案:

答案 0 :(得分:2)

这是一个解决方案,使您的功能适应它:

# load library and data 
library(dplyr, warn.conflicts = F)
iris <- iris 

# cut-points (percentage)
cut_points_1 <- c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 1) 
cut_points_2 <- c(0, 0.2, 0.4, 0.6, 0.8, 1)

# function 
cut <- function(data, var_name, cut_points) {
  var_name <- enquo(var_name)
  varname_cut <- paste0(quo_name(var_name), "_cut")
  tibble(cut_points = cut_points,
         !!varname_cut := data %>% pull(!!var_name) %>% quantile(cut_points))
}

# run
cut(iris, Sepal.Length, cut_points_1)
#> # A tibble: 12 x 2
#>    cut_points Sepal.Length_cut
#>         <dbl>            <dbl>
#>  1       0.00            4.300
#>  2       0.10            4.800
#>  3       0.20            5.000
#>  4       0.30            5.270
#>  5       0.40            5.600
#>  6       0.50            5.800
#>  7       0.60            6.100
#>  8       0.70            6.300
#>  9       0.80            6.520
#> 10       0.90            6.900
#> 11       0.95            7.255
#> 12       1.00            7.900
cut(iris, Sepal.Length, cut_points_2)
#> # A tibble: 6 x 2
#>   cut_points Sepal.Length_cut
#>        <dbl>            <dbl>
#> 1        0.0             4.30
#> 2        0.2             5.00
#> 3        0.4             5.60
#> 4        0.6             6.10
#> 5        0.8             6.52
#> 6        1.0             7.90

我添加了一个带有cut_points的列,以获得类似quantile结果的内容。如果需要,您可以使用%格式化

一些解释

  • 您不需要在enquodata上使用cut_points,因为您不需要在功能中使用它们。它们作为对象传递。
  • 您可以使用quo_name获取您的quosure的名称以将其粘贴
  • 您可以使用dplyr::pull将数据列作为向量,而不是单列 tibble