How do I remove empty data frames from a list?

A slightly simpler and more transparent approach to the sapply/indexing combination is to use the Filter() function:

> Filter(function(x) dim(x)[1] > 0, mlist)
[[1]]
  X1 X2
1  1  3
2  2  4

[[2]]
  X1 X2
1  9 11
2 10 12

Instead of dim(x)[1] you could make use of nrow, so you could do

mlist[sapply(mlist, nrow) > 0]

Filter(function(x) nrow(x) > 0, mlist)

You could also use keep and discard from purrr

purrr::keep(mlist, ~nrow(.) > 0)
purrr::discard(mlist, ~nrow(.) == 0)

There is also compact in purrr which removes all empty elements directly. It is a wrapper on discard

purrr::compact(mlist)

If you are ok to filter the list based on number of columns, you could replace nrow with ncol in above answers. Additionally, you could also use lengths to filter the list.

mlist[lengths(mlist) > 0]

Adding tidyverse option:

library(tidyverse)
mlist[map(mlist, function(x) dim(x)[1]) > 0]


mlist[map(mlist, ~dim(.)[1]) > 0]

I'm not sure if this is exactly what you're asking for, but if you want to trim mlist down to contain only non-empty data frames before running the function on it, try mlist[sapply(mlist, function(x) dim(x)[1]) > 0].

E.g.:

R> M1 <- data.frame(matrix(1:4, nrow = 2, ncol = 2))
R> M2 <- data.frame(matrix(nrow = 0, ncol = 0))
R> M3 <- data.frame(matrix(9:12, nrow = 2, ncol = 2))
R> mlist <- list(M1, M2, M3)
R> mlist[sapply(mlist, function(x) dim(x)[1]) > 0]
[[1]]
  X1 X2
1  1  3
2  2  4

[[2]]
  X1 X2
1  9 11
2 10 12

Tags:

R