JSTAcademy
0 XP
Dashboard
Crash Courses
Data Manipulation with dplyr
18 min
Masters+175 XP
Crash Courses · Masters

Data Manipulation with dplyr

Transform, filter, group, and summarize data frames using dplyr's grammar of data manipulation — the most important R package for analysis.
18 min read+175 XP on completionCert: R Crash Course
Tap any word in the text below to start reading from there.

Data Manipulation with dplyr

Installing and Loading dplyr

install.packages("dplyr")  # run once
library(dplyr)             # load every session

Or install the entire tidyverse at once: install.packages("tidyverse")

---

Sample Data

library(dplyr)

sales <- data.frame(
  id        = 1:10,
  product   = c("Laptop","Phone","Desk","Laptop","Monitor","Phone","Chair","Laptop","Monitor","Desk"),
  category  = c("Electronics","Electronics","Furniture","Electronics","Electronics",
                "Electronics","Furniture","Electronics","Electronics","Furniture"),
  price     = c(1299,799,450,1199,599,849,299,1399,649,399),
  qty       = c(2,5,3,1,4,2,6,3,2,4),
  region    = c("North","South","North","East","West","South","North","East","West","South"),
  stringsAsFactors = FALSE
)

---

The Pipe Operator

# Without pipe (hard to read — inside-out):
arrange(select(filter(sales, category == "Electronics"), product, price), price)

# With pipe (left-to-right, readable):
sales %>%
  filter(category == "Electronics") %>%
  select(product, price) %>%
  arrange(price)

# Native pipe (R 4.1+) — no package needed:
sales |>
  filter(category == "Electronics") |>
  select(product, price) |>
  arrange(price)

---

Core dplyr Verbs

filter() — keep rows matching conditions:

sales %>% filter(price > 800)
sales %>% filter(category == "Electronics", region == "North")
sales %>% filter(price >= 500 & price <= 1000)
sales %>% filter(product %in% c("Laptop", "Phone"))

select() — choose columns:

sales %>% select(product, price, qty)
sales %>% select(-id)              # exclude id
sales %>% select(starts_with("p")) # product, price
sales %>% select(where(is.numeric)) # numeric columns only

mutate() — add or modify columns:

sales %>%
  mutate(
    revenue   = price * qty,
    discount  = if_else(price > 1000, price * 0.1, 0),
    final_rev = revenue - discount,
    category_upper = toupper(category)
  )

arrange() — sort rows:

sales %>% arrange(price)              # ascending
sales %>% arrange(desc(price))        # descending
sales %>% arrange(category, desc(price))  # multi-key sort

group_by() + summarise() — aggregation:

sales %>%
  group_by(category) %>%
  summarise(
    total_revenue = sum(price * qty),
    avg_price     = mean(price),
    n_products    = n(),
    .groups = "drop"
  )
#    category    total_revenue avg_price n_products
# 1  Electronics      23291     882.4      7
# 2  Furniture         5346     382.7      3

# Multiple grouping variables
sales %>%
  group_by(category, region) %>%
  summarise(revenue = sum(price * qty), .groups = "drop") %>%
  arrange(category, desc(revenue))

---

Advanced Operations

# slice — select rows by position
sales %>% slice_max(price, n = 3)  # top 3 most expensive
sales %>% slice_min(qty, n = 2)    # 2 lowest quantity

# rename — rename columns
sales %>% rename(units = qty, item = product)

# count — frequency tables
sales %>% count(category)
sales %>% count(region, sort = TRUE)

# across — apply function to multiple columns
sales %>%
  group_by(category) %>%
  summarise(across(c(price, qty), list(mean = mean, sum = sum)))

# Joins
customers <- data.frame(
  id   = 1:5,
  name = c("Alice", "Bob", "Carol", "David", "Emma")
)
# left_join — keep all rows from sales
left_join(sales, customers, by = "id")

---

Complete Pipeline Example

top_performers <- sales %>%
  mutate(revenue = price * qty) %>%
  group_by(product) %>%
  summarise(
    total_revenue = sum(revenue),
    units_sold    = sum(qty),
    avg_price     = mean(price),
    .groups = "drop"
  ) %>%
  mutate(revenue_share = total_revenue / sum(total_revenue) * 100) %>%
  arrange(desc(total_revenue)) %>%
  slice_head(n = 5)

print(top_performers)
0%