R: removing NULL elements from a list
The closest you'll be able to get is to first name the list elements and then remove the NULLs.
names(x) <- seq_along(x)
## Using some higher-order convenience functions
Filter(Negate(is.null), x)
# $`11`
# [1] 123
#
# $`13`
# [1] 456
# Or, using a slightly more standard R idiom
x[sapply(x, is.null)] <- NULL
x
# $`11`
# [1] 123
#
# $`13`
# [1] 456
Recursive remove NULL elements of list of lists
One approach is to use rrapply
in the rrapply
-package (extension of base rapply
):
library(rrapply)
x <- list(a=1, b=2, c=list(ca=1, cb=2, cc=NULL), d=NULL)
rrapply(x, condition = Negate(is.null), how = "prune")
#> $a
#> [1] 1
#>
#> $b
#> [1] 2
#>
#> $c
#> $c$ca
#> [1] 1
#>
#> $c$cb
#> [1] 2
Benchmark timings
Benchmarking the computation time of rrapply
against rlist's list.clean
function for some large nested lists, I get the following results:
## recursively create nested list with dmax layers and 50% NULL elements
f <- function(len, d, dmax) {
x <- vector(mode = "list", length = len)
for(i in seq_along(x)) {
if(d + 1 < dmax) {
x[[i]] <- Recall(len, d + 1, dmax)
} else {
x[[i]] <- list(1, NULL)
}
}
return(x)
}
## long shallow list (3 layers, total 5e5 nodes)
x_long <- f(len = 500, d = 1, dmax = 3)
microbenchmark::microbenchmark(
rlist = rlist::list.clean(x_long, recursive = TRUE),
rrapply = rrapply::rrapply(x_long, condition = Negate(is.null), how = "prune"),
check = "equal",
times = 5L
)
#> Unit: milliseconds
#> expr min lq mean median uq max neval
#> rlist 2331.4914 2343.3001 2438.9674 2441.3850 2512.3484 2566.3121 5
#> rrapply 353.7169 393.0646 400.8198 399.7971 417.7235 439.7972 5
## deeply nested list (18 layers, total 2^18 nodes)
x_deep <- f(len = 2, d = 1, dmax = 18)
microbenchmark::microbenchmark(
rlist = rlist::list.clean(x_deep, recursive = TRUE),
rrapply = rrapply::rrapply(x_deep, condition = Negate(is.null), how = "prune"),
check = "equal",
times = 5L
)
#> Unit: milliseconds
#> expr min lq mean median uq max neval
#> rlist 2167.2946 2251.5203 2279.9963 2292.5045 2332.4432 2356.2188 5
#> rrapply 268.9463 274.7437 325.9585 292.4559 354.1607 439.4857 5
Extract non null elements from a list in R
Here's another option:
Filter(Negate(is.null), x)
Extract non null elements from a list in R
Here's another option:
Filter(Negate(is.null), x)
Remove null list-columns
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]>
data
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)))
How to Remove Null Values in a List
This would be much easier if you just used Filter()
and Map()
For example
df.numeric.summary <- function(data.frame1){
my_summary <- function(x) c(
"Mean"=mean(x, na.rm = TRUE),
"Median"=median(x, na.rm=TRUE),
"IQR"=IQR(x, na.rm=TRUE))
Map(my_summary, Filter(is.numeric, data.frame1))
}
You can test with
df.numeric.summary(iris)
Related Topics
Horizontal Dendrogram in R with Labels
Creating Multi Column Legend in Ggplot
Solving Simultaneous Equations with R
Row Sums Over Columns with a Certain Pattern in Their Name
Can You Specify Different Geoms for Different Facets in a Ggplot
Possible to Create Rd Help Files for Objects Not in a Package
Setting Work Directory in Knitr Using Opts_Chunk$Set(Root.Dir = ...) Doesn't Work
Create New Column Based on 4 Values in Another Column
Split Time Series Data into Time Intervals (Say an Hour) and Then Plot the Count
How to Retry a Statement on Error
Group Data and Plot Multiple Lines
Left-Adjust Title in Ggplot2, or Absolute Position for Ggtitle