Robert's Data Science Blog

Filter and flatten nested lists

library(magrittr)

Consider a nested list like the following, resembling a JSON file read with jsonlite::read_json:

my_list <- list(
    a = 1,
    b = "foo",
    c = NULL,
    d = list(
        e = 3,
        f = 4
    )
)

I would like to keep only the “top level” entries in the list, that is, the entries that are/should be atomic JSON entries like numbers or strings. In my_list I definitely want to keep a and b and discard d. It is not clear from this context if c should be kept, but I choose to keep it.

First we remove d by noticing that non-atomic entries are lists:

purrr::discard(my_list, is.list) 
## $a
## [1] 1
## 
## $b
## [1] "foo"
## 
## $c
## NULL

If we wanted to remove c this could be passed through another round of discard. Instead I want to turn this into a tibble. However, tibbles do not allow NULL because it doesn’t have a type, so we have to convert it to an NA, choosing the type to be numeric:

my_list %>% 
    purrr::discard(is.list) %>% 
    purrr::modify_if(is.null, ~ NA_real_) %>% 
    tibble::as_tibble()
## # A tibble: 1 x 3
##       a b         c
##   <dbl> <chr> <dbl>
## 1     1 foo      NA