开发者

How do I remove empty data frames from a list?

开发者 https://www.devze.com 2023-01-07 18:54 出处:网络
I\'ve got dozens of lists, each is a collection of 11 dat开发者_StackOverflow中文版a frames. Some data frames are empty (another script did not output any data, not a bug).

I've got dozens of lists, each is a collection of 11 dat开发者_StackOverflow中文版a frames. Some data frames are empty (another script did not output any data, not a bug).

I need to push each list through a function but that chokes when it sees an empty data frame. So how do I write a function that will take a list, do a dim on each element (i.e. data frame) and if it's 0, then skip to the next.

I tried something like this:

empties <- function (mlist)
{
 for(i in 1:length(mlist))
   {
    if(dim(mlist[[i]])[1]!=0) return (mlist[[i]])
    }
}

But clearly, that didn't work. I would do this manually at this point but that would take forever. Help?


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


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]
0

精彩评论

暂无评论...
验证码 换一张
取 消