100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

dplyr Basics

Learn the core dplyr verbs—filter, select, mutate, arrange, summarise, and group_by—for fast, readable data manipulation in R.

Data WranglingBeginner9 min readJul 10, 2026
Analogies

Introduction to dplyr

dplyr is the tidyverse package for manipulating tabular data in R, built around a small set of verbs—filter(), select(), mutate(), arrange(), summarise(), and group_by()—that each do one job well. Because every verb takes a data frame (or tibble) as its first argument and returns a data frame, you can chain them together with the pipe operator (%>% or the base |>) to express a multi-step data transformation as a readable left-to-right sequence rather than a nest of function calls.

🏏

Cricket analogy: Just as a cricket captain calls a sequence of field placements, bowling changes, and batting orders over an innings, dplyr chains filter(), mutate(), and summarise() into a readable over-by-over pipeline instead of one tangled instruction.

The Core Verbs: filter, select, arrange

filter() keeps only the rows that satisfy a logical condition, such as filter(df, age > 30 & country == 'India'), combining multiple conditions with & (AND) and | (OR). select() instead subsets columns, and supports helper functions like starts_with(), contains(), and everything() so you can grab groups of columns by name pattern rather than typing each one; arrange() then reorders the remaining rows by one or more columns, with desc() for descending order.

🏏

Cricket analogy: filter() is like a selector picking only players with a batting average above 40 and at least 50 ODIs, while select() is choosing which columns of the scorecard—runs, strike rate, not fielding position—to display.

r
library(dplyr)

starwars %>%
  filter(species == 'Human', !is.na(height)) %>%
  select(name, height, mass, homeworld) %>%
  mutate(bmi = mass / (height / 100)^2) %>%
  group_by(homeworld) %>%
  summarise(
    avg_bmi = mean(bmi, na.rm = TRUE),
    n = n()
  ) %>%
  arrange(desc(avg_bmi))

Transforming Data: mutate and the Pipe

mutate() creates new columns or overwrites existing ones based on expressions applied to other columns, for example mutate(df, bmi = weight_kg / (height_m^2)), and can create several columns in one call, each able to reference columns defined earlier in the same mutate(). The pipe operator, whether magrittr's %>% or base R's native |>, takes the value on its left and inserts it as the first argument of the function on its right, so df %>% filter(...) %>% mutate(...) reads as 'take df, then filter it, then mutate it' instead of nested calls like mutate(filter(df, ...)).

🏏

Cricket analogy: mutate() is like a scorer adding a derived strike-rate column computed from runs and balls faced for every player, and the pipe reads like a match report narrating toss, then innings, then result in order.

The native pipe |> (introduced in R 4.1) works almost identically to magrittr's %>% for simple chains like df |> filter(...) |> mutate(...), and needs no package load, though %>% still offers extras such as the placeholder dot.

Grouped Summaries: group_by and summarise

group_by() splits a data frame into groups defined by one or more columns without changing its appearance, and every subsequent verb—especially summarise()—is then applied independently within each group; summarise(df, avg_score = mean(score), n = n()) collapses each group down to one row per group containing the requested aggregate statistics. Because grouping persists on the returned tibble, it is good practice to call ungroup() (or use .by = inside a single verb in modern dplyr) once you are done with grouped operations, so later steps in the pipeline don't silently operate group-wise when you expect them not to.

🏏

Cricket analogy: group_by(team) followed by summarise(avg_runs = mean(runs)) is like a scorer grouping every innings by team and computing each team's season batting average in one row per team, rather than one row per innings.

A grouped tibble stays grouped after summarise() (dropping only the last grouping variable), so chaining another summarise() or mutate() without ungroup() can silently aggregate within leftover groups instead of over the whole data frame.

  • dplyr's core verbs—filter(), select(), mutate(), arrange(), summarise(), group_by()—each perform one focused transformation on a data frame.
  • The pipe (%>% or |>) chains verbs left to right, avoiding deeply nested function calls.
  • filter() subsets rows by logical conditions; select() subsets columns, including via helpers like starts_with().
  • mutate() adds or overwrites columns and can reference columns created earlier in the same call.
  • group_by() + summarise() is the standard pattern for computing per-group aggregate statistics.
  • Always ungroup() (or scope with .by =) after grouped operations to avoid unexpected group-wise behavior downstream.
  • arrange() reorders rows, with desc() for descending sort order.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#RProgrammingStudyNotes#DplyrBasics#Dplyr#Core#Verbs#Filter#StudyNotes#SkillVeris#ExamPrep