How to Remove NULL from List and Nested List in R

NULL represents a null object, and sometimes, it’s logical for the project to filter it out from either a list or data frame.

Here are three ways to remove NULL values from a list in R:

  1. Using Filter() with Negate() and is.null()
  2. Using sapply() or lapply() with Subsetting
  3. Using purrr::discard() (Tidyverse Approach)

For example, if you have a list that contains the following values:

main_list = list(11, NULL, "KRUNAL", NULL, 1.9)

In the above main_list, there are two NULL values at positions 2 and 4.

Method 1: Using Filter() with Negate() and is.null()

For checking NULL values in the list, we can use the is.null() function that returns boolean TRUE for NULL value and FALSE otherwise. On top of that, we will use Negate() and Filter() functions to check each element, retain non-NULL values, and remove all the NULL values.

Syntax

filtered_list <- Filter(Negate(is.null), main_list)

Code

main_list <- list(11, NULL, "KRUNAL", NULL, 1.9)

print(main_list)

filtered_list <- Filter(Negate(is.null), main_list)

print(filtered_list)

Output

Removing NULL values from list in R

The Filter() approach helps remove top-level NULL values. However, NULL is not the same as NA or NaN. If you want to find NA values, use the is.na() function.

Pros

  1. It is efficient and faster for larger lists.
  2. It clearly expresses the intent of filtering.
  3. We don’t need external packages.

Cons

  1. If you have nested lists that contain NULL, you must use a different approach, as this approach won’t remove NULL from a nested list.

Method 2: Using sapply() with Subsetting

The sapply() is a base R function that is helpful when applying a specific function to the whole list. If I use is.null() function with sapply(), I would get a list of logical values suggesting which elements are NULL.

Then, I can subset the original list where NULL values are removed using the negation operator (!).

Syntax

main_list[!sapply(main_list, is.null)]

Code

main_list <- list(11, NULL, "KRUNAL", NULL, 1.9)

print(main_list)

without_null_list <- main_list[!sapply(main_list, is.null)]

print(without_null_list)

Output

Removing NULL values from list using lapply() and subsetting

Pros

  1. No external packages are required.

Cons

  1. It requires explicit subsetting and negation, which is slightly slower for very large lists compared to the Filter() approach.

Method 3: Using purrr::discard()

The purrr is a third-party package that provides a discard() function to remove NULL elements that satisfy the is.null predicate.

Install and load the purrr library like this:

library(purrr)

Syntax

filtered_list <- discard(main_list, is.null)

Code

library(purrr)

main_list <- list(11, NULL, "KRUNAL", NULL, 1.9)

print(main_list)

filtered_list <- discard(main_list, is.null)

print(filtered_list)

Output

Filtering NULL values from list using discard() function

Pros

  1. It can handle complex predicates.
  2. It works seamlessly with a tidyverse ecosystem.

Cons

  1. It requires installing and loading purrr.
  2. It is slightly slower for small lists than base R methods (but negligible in most cases).

Removing NULL values from nested lists

We can write a recursive function to traverse the list and remove NULL values at all levels. It requires a recursive approach because NULL values can exist at any level of the list hierarchy.

remove_nulls_recursive <- function(x) {
  # Base case: if x is not a list, return it as is
  if (!is.list(x)) {
    return(x)
  }

  # Recursively apply the function to each element
  x <- lapply(x, remove_nulls_recursive)

  # Remove NULL elements at the current level
  x <- x[!sapply(x, is.null)]

  return(x)
}

nested_list <- list(
 a = 1,
 b = NULL,
 c = list(
   d = NULL,
   e = 2,
   f = list(
     g = NULL,
     h = 3
   )
  )
)
print("Before removing NULLs:")
print(nested_list)

# Remove NULLs
cleaned_list <- remove_nulls_recursive(nested_list)
print("After removing NULLs:")
print(cleaned_list)

Output

[1] "Before removing NULLs:"

$a
 [1] 1

$b
 NULL

$c
 $c$d
  NULL

 $c$e
 [1] 2

 $c$f
  $c$f$g
  NULL

  $c$f$h
  [1] 3



[1] "After removing NULLs:"

$a
[1] 1

$c
$c$e
[1] 2

$c$f
$c$f$h
[1] 3

That’s all!

Leave a Comment