purrr::keep() / purrr::discard() / purrr::compact()

keep(.x, .p, ...)
discard(.x, .p, ...)
compact(.x, ...)
Returns: list or atomic · Updated March 13, 2026 · Tidyverse
purrr functional-programming filtering lists

These purrr functions filter elements in a list or vector based on a predicate function. keep() retains elements where the predicate returns TRUE, discard() does the opposite, and compact() removes NULL, empty strings, and zero-length elements.

Syntax

keep(.x, .p, ...)
discard(.x, .p, ...)
compact(.x, ...)

Parameters

ParameterTypeDefaultDescription
.xlist or atomicA vector or list to filter
.pfunctionA predicate function that returns TRUE/FALSE
...additional argumentsAdditional arguments passed to .p

For compact(), .x is the only required parameter.

Examples

Basic usage with keep()

library(purrr)

# Keep even numbers
x <- list(1, 2, 3, 4, 5, 6)
keep(x, ~ .x %% 2 == 0)
# [[1]]
# [1] 2
# [[2]]
# [1] 4
# [[3]]
# [1] 6

Using discard() to remove elements

# Remove NULL and NA values
y <- list(1, NULL, 3, NA, 5)
discard(y, is.null)
# [[1]]
# [1] 1
# [[2]]
# [1] 3
# [[3]]
# [1] NA
# [[4]]
# [1] 5

# Discard empty strings
z <- list("apple", "", "banana", "cherry", "")
discard(z, ~ .x == "")
# [[1]]
# [1] "apple"
# [[2]]
# [1] "banana"
# [[3]]
# [1] "cherry"

Using compact() for quick cleanup

# Remove NULL and empty elements
data <- list(name = "Alice", email = NULL, age = 30, notes = "")
compact(data)
# $name
# [1] "Alice"
# $age
# [1] 30

# Compact works with all empty types
mixed <- list(1, NULL, "", character(0), NA, "hello")
compact(mixed)
# [[1]]
# [1] 1
# [[2]]
# [1] "hello"

Common Patterns

Conditional element removal

# Remove elements based on type
mixed_types <- list(1, "a", 2, "b", NULL, 3)
discard(mixed_types, is.null)
# [[1]]
# [1] 1
# [[2]]
# [1] "a"
# ...

# Keep only numeric values
keep(mixed_types, is.numeric)
# [[1]]
# [1] 1
# [[2]]
# [1] 2
# [[3]]
# [1] 3

Data cleaning pipelines

library(dplyr)

# Clean up a data frame with some missing values
df <- data.frame(
  name = c("Alice", NA, "Bob", "Charlie"),
  value = c(10, 20, NA, 40)
)

# Compact rows (remove rows with any NA)
df %>% pmap(~ c(...)) %>% compact() %>% matrix(ncol = 2, byrow = TRUE) %>% as.data.frame()

See Also