Another option is to use map to iterate over the sets of grouping columns and then reduce for merging. For example:
library(tidyverse)
list("Species", c("Species", "Petal.Length")) %>%
set_names(c("_Species", "_Species_Petal.Length")) %>%
map(~iris %>%
group_by_at(.x) %>%
summarize(p = sum(Petal.Width))) %>%
reduce(left_join, by="Species", suffix=names(.)) %>%
select(Species, Petal.Length, everything())
# A tibble: 48 x 4
Species Petal.Length p_Species p_Species_Petal.Length
<fct> <dbl> <dbl> <dbl>
1 setosa 1 12.3 0.2
2 setosa 1.1 12.3 0.1
3 setosa 1.2 12.3 0.4
4 setosa 1.3 12.3 1.8
5 setosa 1.4 12.3 2.7
6 setosa 1.5 12.3 3.1
7 setosa 1.6 12.3 2
8 setosa 1.7 12.3 1.4
9 setosa 1.9 12.3 0.6
10 versicolor 3 66.3 1.1
# … with 38 more rows
You can use the map approach to summarize over multiple sets of grouping columns and return a long summary data frame. For example:
# Add a couple of grouping columns to iris
set.seed(2)
dat = iris %>%
mutate(Group1=sample(c("A","B"), 150, replace=TRUE),
Group2=sample(c("d","e"), 150, replace=TRUE))
# Get all combinations of 0 through 2 groups
map(0:2, ~combn(c("Species", "Group1","Group2"), .x, simplify=FALSE)) %>%
flatten() %>%
# Run summarise on each of the group sets created above
map_df(~dat %>%
group_by_at(.x) %>%
summarise(N=n(),
Petal.Width=mean(Petal.Width))) %>%
# Replace NA with "All" (representing marginalizing over that column)
mutate_if(is.factor, as.character) %>%
map_if(~!is.numeric(.), ~replace_na(., replace="All")) %>%
bind_rows()
N Petal.Width Species Group1 Group2
1 150 1.1993333 All All All
2 50 0.2460000 setosa All All
3 50 1.3260000 versicolor All All
4 50 2.0260000 virginica All All
5 81 1.2444444 All A All
6 69 1.1463768 All B All
7 76 1.1447368 All All d
8 74 1.2554054 All All e
9 25 0.2640000 setosa A All
10 25 0.2280000 setosa B All
11 30 1.3466667 versicolor A All
12 20 1.2950000 versicolor B All
13 26 2.0692308 virginica A All
14 24 1.9791667 virginica B All
15 28 0.2500000 setosa All d
16 22 0.2409091 setosa All e
17 23 1.3521739 versicolor All d
18 27 1.3037037 versicolor All e
19 25 1.9560000 virginica All d
20 25 2.0960000 virginica All e
21 41 1.2048780 All A d
22 40 1.2850000 All A e
23 35 1.0742857 All B d
24 34 1.2205882 All B e