如何在R中对子集操作后的列表中删除空数据框?

3
假设我正在从一个名为“data.frame”的有命名的列表中根据名为“long”的子集变量进行子集化。
子集化后,列表中的一些“data.frame”可能为空,因为它们没有匹配的子集化。
我想知道如何在最终输出中删除所有这些空的“data.frame”。
下面是一个简单的示例和我的不成功的解决方案:
b <- list(Study1 = data.frame(d = 6:8, long = c(F, F,F)), Study2 = data.frame(d = 9:11, long = c(T, T, F)) )


( h <- lapply(b, subset, subset = long) ) ## subset with respect to "long"

## OUTPUT:

   $Study1
   [1] d    long
    <0 rows> (or 0-length row.names)   ## This data.frame is empty!! must be deleted ##!

   $Study2
    d long
    1  9 TRUE
    2 10 TRUE


## I tried the following with no success: ##

for(i in 1:2) if(nrow(h[[i]]) == 0) h[[i]] <- NULL else h[[i]]
3个回答

8

只需按行数筛选:Filter

new_list_of_dfs <- Filter(NROW, list_of_dfs)

1
我们可以使用keep
library(purrr)
keep(h, ~ nrow(.x) > 0)
#$Study2
#   d long
#1  9 TRUE
#2 10 TRUE

或者使用来自base Rsapply创建逻辑条件并Extractlist元素。

h[sapply(h, nrow) > 0]

1
akrun的答案是可行的,但要理解为什么你最后一行代码不起作用(for(i in 1:2) if(nrow(h[[i]]) == 0) h[[i]] <- NULL else h[[i]]):这是因为你在循环完成之前删除了列表中的一个元素。因此,先将查询保存在索引中,然后使用该查询结果在第二行中删除元素。虽然冗长但更有助于学习。
index <- vector(mode = 'logical', length = length(h)) #initialize index as all FALSE
for (i in 1:length(h)) { #this is your last line of code, modified
  if(nrow(h[[i]]) != 0) {
    index[i] <- TRUE
    } else {next} 
}
h <- h[index]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接