dplyr Basics

Reviewed & published by Brayan K

dplyr is a tidyverse package for transforming data frames with a small set of readable verbs — filter, select, mutate, and arrange — that you chain together with the pipe.

Part of the free R course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

By the end of this lesson you'll filter rows, select and add columns, sort data, and combine these verbs into a single readable pipeline with the pipe operator.

What You'll Learn in This Lesson

1️⃣ filter() and select()

filter() keeps rows matching a condition; select() keeps columns. Inside dplyr verbs you refer to columns by bare name — no df$ needed.

library(dplyr)

# A small data frame to work with:
df <- data.frame(
  name = c("Ada", "Bob", "Cara", "Dan"),
  dept = c("eng", "sales", "eng", "sales"),
  salary = c(95, 60, 88, 72)
)

# filter() keeps rows that match a condition:
filter(df, salary > 80)
#   name dept salary
# 1  Ada  eng     95
# 2 Cara  eng     88

# select() keeps columns:
select(df, name, salary)

2️⃣ mutate() and arrange()

mutate() adds new columns computed from existing ones; arrange() sorts rows, with desc() for descending order.

library(dplyr)

df <- data.frame(
  product = c("pen", "pad", "ink"),
  price = c(2.5, 5.0, 9.0),
  units = c(120, 80, 45)
)

# mutate() ADDS or changes columns:
df2 <- mutate(df, revenue = price * units)

# arrange() SORTS rows (desc() for descending):
arrange(df2, desc(revenue))
#   product price units revenue
# 1     ink   9.0    45     405
# 2     pad   5.0    80     400
# 3     pen   2.5   120     300

3️⃣ Chaining with the Pipe

The real power comes from chaining. The pipe |> passes each step's result into the next, so a multi-step transformation reads top to bottom like a sentence.

library(dplyr)

df <- data.frame(
  name = c("Ada", "Bob", "Cara", "Dan"),
  dept = c("eng", "sales", "eng", "sales"),
  salary = c(95, 60, 88, 72)
)

# The pipe |> (or %>%) passes the result on to the next verb,
# so you read the steps top to bottom like a sentence.
df |>
  filter(dept == "eng") |>      # 1. keep engineers
  mutate(bonus = salary * 0.1) |>  # 2. add a bonus column
  select(name, bonus) |>        # 3. keep two columns
  arrange(desc(bonus))          # 4. highest bonus first

Your turn. Fill in the ___ blank, run it, and compare with the expected output.

library(dplyr)

# 🎯 YOUR TURN — replace each ___ then run it.

orders <- data.frame(
  item = c("a", "b", "c", "d"),
  qty = c(3, 10, 1, 6),
  price = c(20, 5, 50, 8)
)

result <- orders |>
  mutate(total = qty * price) |>
  ___ |>   # 👉 replace ___ with filter(total > 40)
  arrange(desc(total))

print(result)

# ✅ Expected output:
#   item qty price total
# 1    a   3    20    60
# 2    b  10     5    50
# 3    c   1    50    50
# 4    d   6     8    48

Mini-Challenge: Top Earners

Write the whole pipeline from the outline, run it, and check it against the example output. This is the core dplyr workflow you'll use daily.

# 🎯 MINI-CHALLENGE: top earners report.
#
# Start from this data frame:
#   staff <- data.frame(
#     name = c("Mia","Leo","Zoe","Sam","Ari"),
#     team = c("X","Y","X","Y","X"),
#     pay  = c(70, 110, 95, 60, 130)
#   )
#
# Using a pipe, in one chain:
# 1. mutate() a column "raise" = pay * 0.05
# 2. filter() to keep pay >= 90
# 3. select() name and raise
# 4. arrange() by raise, highest first
#
# ✅ Example output:
#   name raise
# 1  Ari  6.50
# 2  Leo  5.50
# 3  Zoe  4.75

# your code here

Common Errors (and the fix)

Pro Tips

📋 Quick Reference — dplyr Verbs

VerbWhat it does
filter(df, x > 1)keep rows matching a condition
select(df, a, b)keep (or drop) columns
mutate(df, c = a + b)add or change a column
arrange(df, desc(x))sort rows
df |> verb()pipe into the next step
library(dplyr)load the package

🎉 Lesson Complete!

Practice quiz

Which dplyr verb keeps only the ROWS that match a condition?

  • select()
  • filter()
  • mutate()
  • arrange()

Answer: filter(). filter() keeps rows matching a condition; select() chooses columns.

Which verb chooses (keeps or drops) COLUMNS?

  • select()
  • filter()
  • summarise()
  • arrange()

Answer: select(). select() picks columns; filter() picks rows.

Which verb ADDS or changes a column computed from existing ones?

  • arrange()
  • filter()
  • mutate()
  • select()

Answer: mutate(). mutate() creates or modifies columns.

Which verb SORTS the rows of a data frame?

  • group_by()
  • select()
  • filter()
  • arrange()

Answer: arrange(). arrange() sorts rows; wrap a column in desc() for descending order.

How do you sort in DESCENDING order with arrange()?

  • arrange(desc(x))
  • arrange(-sort(x))
  • arrange(x, rev = TRUE)
  • arrange(descending(x))

Answer: arrange(desc(x)). arrange(df, desc(x)) sorts by x from high to low.

What does the pipe in df |> filter(x > 1) do?

  • Comments out the filter call
  • Passes df as the first argument to filter()
  • Runs filter() before df is created
  • Compares df with the filter result

Answer: Passes df as the first argument to filter(). The pipe feeds the left-hand value as the first argument to the right-hand function.

Inside a dplyr verb, how do you refer to a column named salary?

  • By the bare name salary
  • Always as df$salary
  • As "salary" in quotes
  • As .salary

Answer: By the bare name salary. dplyr verbs let you use bare column names; no df$ prefix is needed.

Which function loads dplyr at the start of a session?

  • import(dplyr)
  • require.dplyr()
  • library(dplyr)
  • use(dplyr)

Answer: library(dplyr). library(dplyr) attaches the package so its verbs are available.

Inside filter(), how do you test that dept equals "eng"?

  • dept = "eng"
  • dept == "eng"
  • dept -> "eng"
  • dept := "eng"

Answer: dept == "eng". Use == for equality; a single = is assignment and is wrong here.

Which native pipe operator works in base R 4.1+ without any package?

  • %>%
  • ->>
  • |>
  • %|%

Answer: |>. |> is the native pipe in R 4.1+; %>% comes from magrittr/dplyr.

Continue this course

Frequently asked questions

What is dplyr and why is it so popular?

dplyr is a package in the tidyverse for manipulating data frames with a small set of verb functions: filter() for rows, select() for columns, mutate() to add columns, arrange() to sort, and summarise() to aggregate. Its appeal is readability — code reads like a description of what you want, and the steps chain together cleanly. It's also fast and consistent. Once you learn the five core verbs, you can express almost any data transformation.

What does the pipe operator do?

The pipe (|> in modern R, or %>% from the magrittr/dplyr package) takes the result on its left and feeds it as the first argument to the function on its right. So df |> filter(x > 1) is the same as filter(df, x > 1). Chained together, pipes let you read a sequence of transformations top-to-bottom like a recipe — 'take the data, then filter, then mutate, then arrange' — instead of nesting functions inside out.

How is dplyr different from base R data frame operations?

You can do everything dplyr does with base R — df[df$x > 1, ] for filtering, df$new <- ... for new columns — but dplyr is usually more readable and less error-prone, especially as operations stack up. dplyr lets you refer to columns by bare name (no df$ prefix inside verbs) and chain steps with the pipe. Base R is always available and worth knowing; dplyr is the everyday tool most analysts reach for.

Do I need to install anything to use dplyr?

Yes — dplyr isn't part of base R, so install it once with install.packages("dplyr") (or install.packages("tidyverse") to get dplyr plus its companions). Then load it in each session with library(dplyr). The native pipe |> works without any package in R 4.1+; the older %>% pipe comes with dplyr/magrittr. After that, all the verbs in this lesson are available.