Reputation: 993
I would like to create a list of functions and put them in a dataframe. It makes it easier for me to manipulate the functions for the rest of my work. I want to put the ecdf and the quantile functions while grouping on a columns of characters/factors.
I did something like this:
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)))
The ecdf works as expected:
> 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
But the quantile one gives 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
I know that the quantilef
works, because it works outside the dataframe:
> qfsl = quantilef(x = iris$Sepal.Length)
> qfsl(0.5)
50%
5.8
What is going on? How do i get around this?
Upvotes: 1
Views: 55
Reputation: 174468
I think the problem is that when you are creating the list of functions for qf_
, you are passing in a parameter, x
which is lazily evaluated. When you go to call the function, the x
no longer exists in the calling environment.
One way round this is to wrap x
in a quosure
which is evaluated at the point your function is called.
Here's a 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
Created on 2020-04-14 by the reprex package (v0.3.0)
Upvotes: 3