Reputation: 4889
How to get the following code to work without quotes or tilde?
This is important to me because I am using this standalone code inside a custom function where introducing quotes or tilde complicates things.
Thanks.
dataframe <- as.data.frame(cbind(gender = c("male", "female", "female", "female", "male", "female", "male"),
pet = c("dog", "cat", "dog", "cat", "cat", "cat", "dog")))
library(dplyr)
## with tilde
dplyr::group_by_(dataframe, .dots = c(~gender, ~pet)) %>%
dplyr::summarize(counts = n()) %>%
dplyr::mutate(perc = (counts / sum(counts)) * 100) %>%
dplyr::arrange(desc(perc))
#> # A tibble: 4 x 4
#> # Groups: gender [2]
#> gender pet counts perc
#> <fct> <fct> <int> <dbl>
#> 1 female cat 3 75.0
#> 2 male dog 2 66.7
#> 3 male cat 1 33.3
#> 4 female dog 1 25.0
## with quotes
dplyr::group_by_(dataframe, .dots = c('gender', 'pet')) %>%
dplyr::summarize(counts = n()) %>%
dplyr::mutate(perc = (counts / sum(counts)) * 100) %>%
dplyr::arrange(desc(perc))
#> # A tibble: 4 x 4
#> # Groups: gender [2]
#> gender pet counts perc
#> <fct> <fct> <int> <dbl>
#> 1 female cat 3 75.0
#> 2 male dog 2 66.7
#> 3 male cat 1 33.3
#> 4 female dog 1 25.0
## without tilde
dplyr::group_by_(dataframe, .dots = c(gender, pet)) %>%
dplyr::summarize(counts = n()) %>%
dplyr::mutate(perc = (counts / sum(counts)) * 100) %>%
dplyr::arrange(desc(perc))
#> Error in compat_lazy_dots(.dots, caller_env(), ...): object 'gender' not found
Upvotes: 3
Views: 1485
Reputation: 428
Two ways multiple grouping using dplyr programming:-
Way1
f1<-function(df,...){
grp_vars<-quos(...)
df %>%
group_by(!!!grp_vars) %>%
summarize(counts= n()) %>%
mutate(perc = (counts/sum(counts))*100) %>%
arrange(desc(perc))
}
f1(dataframe, gender, pet)
Result1:
# A tibble: 4 x 4
# Groups: gender [2]
gender pet counts perc
<fct> <fct> <int> <dbl>
1 female cat 3 75.0
2 male dog 2 66.7
3 male cat 1 33.3
4 female dog 1 25.0
Way2:
f2<-function(df, grp_vars){
df %>%
group_by(!!!grp_vars) %>%
summarize(counts= n()) %>%
mutate(perc = (counts/sum(counts))*100) %>%
arrange(desc(perc))
}
f2(dataframe, quos(gender,pet))
Result2:
# A tibble: 4 x 4
# Groups: gender [2]
gender pet counts perc
<fct> <fct> <int> <dbl>
1 female cat 3 75.0
2 male dog 2 66.7
3 male cat 1 33.3
4 female dog 1 25.0
Upvotes: 2
Reputation: 887501
If we need to use it in a function, then pass the groups as a quosure and evaluate with !!!
f1 <- function(dat, groups) {
dat %>%
group_by(!!! groups) %>%
summarize(counts = n()) %>%
mutate(perc = (counts / sum(counts)) * 100) %>%
arrange(desc(perc))
}
f1(dataframe, quos(gender, pet))
# A tibble: 4 x 4
# Groups: gender [2]
# gender pet counts perc
# <fctr> <fctr> <int> <dbl>
#1 female cat 3 75.0
#2 male dog 2 66.7
#3 male cat 1 33.3
#4 female dog 1 25.0
In addition to the above, we can have ...
as argument for groups, convert it to strings with quo_name
and pass it on group_by_at
f2 <- function(dat, ...) {
groups <- rlang::enquos(...) %>%
purrr::map_chr(quo_name)
dat %>%
group_by_at(vars(groups)) %>%
summarize(counts = n()) %>%
mutate(perc = (counts / sum(counts)) * 100) %>%
arrange(desc(perc))
}
f2(dataframe, gender, pet)
Upvotes: 3
Reputation: 20095
Use group_by
instead:
dplyr::group_by(dataframe, gender, pet) %>%
dplyr::summarize(counts = n()) %>%
dplyr::mutate(perc = (counts / sum(counts)) * 100) %>%
dplyr::arrange(desc(perc))
#The result:
# Groups: gender [2]
# gender pet counts perc
# <fctr> <fctr> <int> <dbl>
#1 female cat 3 75.0
#2 male dog 2 66.7
#3 male cat 1 33.3
#4 female dog 1 25.0
Upvotes: 2