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.

Leave a Comment

Your email address will not be published. Required fields are marked *