R Filter and Select

Filter and select are two of the most used dplyr operations. Filter keeps specific rows. Select keeps specific columns. Together they let you focus on exactly the slice of your data that matters for a given analysis.

filter() Deep Dive

library(dplyr)

sales <- data.frame(
  product  = c("A","B","C","A","B","C","A"),
  region   = c("N","N","S","S","S","N","N"),
  revenue  = c(1200,800,1500,900,1100,700,1300),
  returned = c(FALSE,TRUE,FALSE,FALSE,TRUE,FALSE,FALSE)
)

Single Condition

filter(sales, region == "N")           # North only
filter(sales, revenue > 1000)          # high revenue
filter(sales, !returned)               # not returned

Multiple Conditions (AND)

# Both conditions must be true
filter(sales, region == "N" & revenue > 1000)

# Equivalent shorthand (comma = AND in filter)
filter(sales, region == "N", revenue > 1000)

Multiple Conditions (OR)

filter(sales, product == "A" | revenue > 1300)

Filter by Value in a List

filter(sales, product %in% c("A","C"))      # product A or C
filter(sales, !product %in% c("B"))         # exclude B

Filter with String Patterns

library(stringr)
products <- data.frame(name=c("Apple","Apricot","Banana","Avocado"))

filter(products, startsWith(name, "A"))
filter(products, str_detect(name, "an"))   # contains "an"

Filter for Missing and Non-Missing Values

data <- data.frame(x=c(1,NA,3,NA,5), y=c("a","b",NA,"d","e"))

filter(data, is.na(x))      # rows where x is NA
filter(data, !is.na(x))     # rows where x is NOT NA
filter(data, complete.cases(data))  # no NAs anywhere in row

select() Deep Dive

employees <- data.frame(
  emp_id   = 1:5,
  name     = c("Asha","Balu","Cena","Dev","Eva"),
  dept     = c("HR","IT","IT","Finance","HR"),
  salary   = c(45000,72000,68000,55000,50000),
  years    = c(3,7,5,4,2),
  active   = c(T,T,F,T,T)
)

Select Specific Columns

select(employees, name, dept, salary)
select(employees, emp_id:salary)        # range of columns
select(employees, -emp_id, -active)     # exclude these columns

Select Helpers

select(employees, starts_with("emp"))    # columns starting with "emp"
select(employees, ends_with("id"))       # columns ending with "id"
select(employees, contains("ar"))        # columns containing "ar"
select(employees, where(is.numeric))     # only numeric columns
select(employees, where(is.character))   # only character columns

Reorder and Rename While Selecting

select(employees, name, everything())          # name first, rest unchanged
select(employees, employee=name, pay=salary)  # rename while selecting

Combining filter() and select() in a Pipeline

employees |>
  filter(active == TRUE & salary > 50000) |>
  select(name, dept, salary) |>
  arrange(desc(salary))

#   name    dept  salary
# 1 Balu    IT    72000
# 2 Cena    IT    68000
# (Cena excluded — active=FALSE, so only Balu matches)

slice() — Select Rows by Position

slice(employees, 1:3)           # first 3 rows
slice_head(employees, n=2)      # first 2
slice_tail(employees, n=2)      # last 2
slice_max(employees, salary, n=2)   # 2 highest salaries
slice_min(employees, salary, n=2)   # 2 lowest salaries
slice_sample(employees, n=3)    # 3 random rows

Filter and select are the two operations you will use in almost every analysis. Filter removes noise from your data. Select focuses on the columns you actually need. Together, they make subsequent analysis faster, cleaner, and easier to understand.

Leave a Comment

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