我想创建一个函数列表并将它们放在数据帧中。它使我更容易为其余工作操作函数。我想将 ecdf 和分位数函数放在分组到字符/因子列上。
我做了这样的事情:
library(tidyverse)
quantilef = function(x) {
qf = function(p){
return(quantile(x, probs = p))
}
return(qf)
}
ecdfdf = iris %>%
group_by(Species) %>%
summarise(ecdf_ = list(ecdf(Sepal.Length)),
qf_ = list(quantilef(x = Sepal.Length)))
ecdf 按预期工作:
> ecdfdf %>% mutate(p = map_dbl(.x = ecdf_, .f = ~.x(5)))
# A tibble: 3 x 4
Species ecdf_ qf_ p
<fct> <list> <list> <dbl>
1 setosa <ecdf> <fn> 0.56
2 versicolor <ecdf> <fn> 0.06
3 virginica <ecdf> <fn> 0.02
但是分位数给出NA
:
> ecdfdf %>% mutate(q10 = map_dbl(.x = qf_, .f = ~.x(0.5)))
# A tibble: 3 x 4
Species ecdf_ qf_ q10
<fct> <list> <list> <dbl>
1 setosa <ecdf> <fn> NA
2 versicolor <ecdf> <fn> NA
3 virginica <ecdf> <fn> NA
我知道quantilef
有效,因为它在数据帧之外工作:
> qfsl = quantilef(x = iris$Sepal.Length)
> qfsl(0.5)
50%
5.8
这是怎么回事?我该如何解决这个问题?
我认为问题是,当您为qf_
创建函数列表时,您正在传入一个参数,x
该参数是延迟计算的。当您去调用函数时,调用环境中不再存在x
。
一种方法是将x
包装在调用函数时计算的quosure
中。
这是一个reprex:
library(tidyverse)
quantilef = function(x) {
y <- rlang::new_quosure(x)
qf <- function(p){
return(quantile(rlang::eval_tidy(y), probs = p))
}
return(qf)
}
ecdfdf = iris %>%
group_by(Species) %>%
summarise(ecdf_ = list(ecdf(Sepal.Length)),
qf_ = list(quantilef(x = Sepal.Length)))
ecdfdf %>% mutate(q10 = map_dbl(.x = qf_, .f = ~.x(0.5)))
#> # A tibble: 3 x 4
#> Species ecdf_ qf_ q10
#> <fct> <list> <list> <dbl>
#> 1 setosa <ecdf> <fn> 5
#> 2 versicolor <ecdf> <fn> 5.9
#> 3 virginica <ecdf> <fn> 6.5
创建于 2020-04-14 由 reprex 软件包 (v0.3.0)