Reproducible example
cats <-
data.frame(
name = c(letters[1:10]),
weight = c(rnorm(5, 10, 1), rnorm(5, 20, 3)),
type = c(rep("not_fat", 5), rep("fat", 5))
)
get_means <- function(df, metric, group) {
df %>%
group_by(.[[group]]) %>%
mutate(mean_stat = mean(.[[metric]])) %>%
pull(mean_stat) %>%
unique()
}
get_means(cats, metric = "weight", group = "type")
What I tried
I expect to get two values back, instead I get one value. It appears that the groupby is failing.
I tried everything including using quo(), eval() and substitute(), UQ(), !!, and a whole host of other things to try and make the stuff inside the group_by() work.
This seems awfully simple but I can't figure it out.
Reasoning for code
The decision for variables to be in quotes is because I am using them in ggplot aes_string() calls. I excluded ggplot code inside the function to simplify the code, otherwise it'd be easy because we could use standard evaluation.
using
*_at
functions :data
I think the "intended" way to do this in the tidyeval framework is to enter the arguments as names (rather than strings) and then quote the arguments using
enquo()
.ggplot2
understands tidy evaluation operators so this works forggplot2
as well.First, let's adapt the
dplyr
summary function in your example:Now add in ggplot:
I'm not sure what type of plot you have in mind, but you can plot the data and summary values using tidy evaluation. For example:
FYI, you can allow the function to take any number of grouping variables (including none) using the
...
argument andenquos
instead ofenquo
(which also requires the use of!!!
(unquote-splice) instead of!!
(unquote)).I would go with slight modification (if I understand correctly what you would like to achive):
gives exactly same output as :
The magrittr pronoun
.
represents the whole data, so you've taken the mean of all observations. Instead, use the tidy eval pronoun.data
which represents the slice of data frame for the current group:If you want to use strings for the names, as in your example, the correct way to do this is to convert the string to a symbol with
sym
and unquote with!!
:If you want to use bare names in your function, then use
enquo
with!!
:What is happening in your example?
Interestingly
.[[group]]
, does work for grouping, but not the way you think. This subsets the stated column of the dataframe as a vector, then makes that a new variable that it groups on:Your problem comes with the
mutate
statement. Instead of selecting the,mutate(mean_stat = mean(.[['weight']]))
simply extracts theweight
column as a vector, computes the mean, and then assigns that single value to the new column