R Group By and Summarise
Group by and summarise work as a pair. group_by() splits your data into groups based on one or more columns. summarise() then computes a summary statistic for each group. This combination answers questions like "What is the average salary per department?" or "How many orders did each region place each month?"
How group_by + summarise Work
Without grouping: With grouping by department:
───────────────────────────── ────────────────────────────────────
All rows treated as one unit Rows split into groups first
mean(salary) = overall mean mean(salary) = mean per department
Diagram:
Original data: After group_by(department):
Asha | HR | 45000 HR group: Asha(45k), Eva(50k)
Balu | IT | 72000 IT group: Balu(72k), Cena(68k)
Cena | IT | 68000 Finance: Dev(55k)
Dev | Fin | 55000
Eva | HR | 50000
summarise gives mean per group
Basic group_by + summarise
library(dplyr)
employees <- data.frame(
name = c("Asha","Balu","Cena","Dev","Eva","Farhan"),
dept = c("HR","IT","IT","Finance","HR","IT"),
salary = c(45000,72000,68000,55000,50000,80000),
exp = c(3,7,5,4,2,9)
)
employees |>
group_by(dept) |>
summarise(
headcount = n(),
avg_salary = mean(salary),
max_salary = max(salary),
total_payroll = sum(salary),
avg_exp = round(mean(exp), 1)
)
Output:
dept headcount avg_salary max_salary total_payroll avg_exp 1 Finance 1 55000 55000 55000 4.0 2 HR 2 47500 50000 95000 2.5 3 IT 3 73333 80000 220000 7.0
Useful Summarise Functions
Function Description ────────────────────────────────────────────────────────────── n() Count rows in group n_distinct(x) Count unique values mean(x) Average median(x) Median sum(x) Total min(x), max(x) Minimum, maximum sd(x), var(x) Standard deviation, variance first(x) First value in group last(x) Last value in group nth(x, 2) Nth value in group
Group by Multiple Columns
sales <- data.frame(
region = c("N","N","S","S","N","S"),
product = c("A","B","A","B","A","B"),
revenue = c(1000,800,1200,900,1100,750)
)
sales |>
group_by(region, product) |>
summarise(
orders = n(),
total_rev = sum(revenue),
avg_rev = mean(revenue),
.groups = "drop" # removes grouping after summarise
)
Filter Within Groups
# Get the top earner in each department employees |> group_by(dept) |> filter(salary == max(salary)) # Get employees above department average salary employees |> group_by(dept) |> filter(salary > mean(salary))
Mutate Within Groups
# Add a column showing salary rank within each department
employees |>
group_by(dept) |>
mutate(
dept_rank = rank(desc(salary)),
dept_avg_sal = mean(salary),
pct_above_avg = round((salary - mean(salary))/mean(salary)*100, 1)
)
count() — Quick Frequency Table
# count() is shorthand for group_by() + summarise(n()) employees |> count(dept) # dept n # 1 Finance 1 # 2 HR 2 # 3 IT 3 employees |> count(dept, sort=TRUE) # sorted by count descending
Removing Grouping
grouped_data <- employees |> group_by(dept) ungrouped <- ungroup(grouped_data) # Or use .groups="drop" inside summarise() employees |> group_by(dept) |> summarise(avg=mean(salary), .groups="drop")
Group by and summarise are the heart of aggregation in R. Every business report — sales by region, average scores by class, orders by product category — uses this pattern. Once you master it, you can answer nearly any "how many / how much per group" question about your data in seconds.
