Reputation: 169
I have a data frame with null list columns, similar to this:
null_list <- list(NULL, NULL, NULL) %>% enframe()
null_list
# name value
# <int> <list>
#1 1 <NULL>
#2 2 <NULL>
#3 3 <NULL>
I'd like to remove all columns that only contain NULL values like the "value" column above, because when I try to unnest_wider these columns (as part of a loop), I receive the error "replacement has length zero."
Upvotes: 2
Views: 546
Reputation: 887531
We could use select_if
. NULL
doesn't exist within a vector
. So, the condition should be to check if the column is a list
and if all
the elements are NULL
(is.null
), negate (!
) to select
all the other columns
library(dplyr)
library(purrr)
null_list %>%
select_if(~ !(is.list(.) && all(map_lgl(., is.null))))
# A tibble: 3 x 1
# name
# <int>
#1 1
#2 2
#3 3
NOTE: This check if all the values in the list
are NULL
and then it removes those columns
If it is deeply nested,
example %>%
select(where(~ !(is.list(.) && is.null(unlist(.)))))
# A tibble: 3 x 3
# a b c
# <dbl> <dbl> <list>
#1 1 4 <NULL>
#2 2 5 <NULL>
#3 3 6 <list [3]>
Or to select only the list
column with any non-NULL elements
example %>%
select(where(~ is.list(.) && !is.null(unlist(.))))
# A tibble: 3 x 1
# c
# <list>
#1 <NULL>
#2 <NULL>
#3 <list [3]>
example <- tibble(a = c(1, 2, 3), b = c(4, 5, 6),
c = list(NULL, NULL, list(1,2,3)),
d = list(NULL, NULL, list(x = NULL, y = NULL, z = NULL)))
Upvotes: 2
Reputation: 1224
Like this?
library(tibble)
null_list <- list(NULL, NULL, NULL) %>% enframe()
> null_list
# A tibble: 3 x 2
name value
<int> <list>
1 1 <NULL>
2 2 <NULL>
3 3 <NULL>
null_list <- rbind(null_list, c(3, "a"))
> null_list
# A tibble: 4 x 2
name value
<chr> <list>
1 1 <NULL>
2 2 <NULL>
3 3 <NULL>
4 3 <chr [1]>
null_list <- null_list[!unlist(lapply(null_list$value, is.null)),]
null_list
> null_list
# A tibble: 1 x 2
name value
<chr> <list>
1 3 <chr [1]>
Upvotes: 1
Reputation: 79288
In Base R, you could do:
null_list[colSums(sapply(null_list,lengths))>0]
# A tibble: 3 x 1
name
<int>
1 1
2 2
3 3
You could also use select_if
from tidyverse
library(tidyverse)
null_list %>%
select_if(map_lgl(.,~sum(lengths(.x))>0))
# A tibble: 3 x 1
name
<int>
1 1
2 2
3 3
Upvotes: 1