7

我有一个数据框列表,并想从 mylist 中删除那些少于 2 行的数据框:

a<-data.frame(x=c(1:4),y=c("m", "n", "o", "p"))
b<-data.frame(x=c(2:6),y=c("q", "w", "e", "r", "t"))
c<-data.frame(x=c(6,7),y=c("j","k"),z=c("$","#"))
d<-data.frame(x="9",y="q",z="+")
mylist<-list(a,b,c,d)

for (i in length(mylist)){
if (nrow(mylist[[i]])<=2){
mylist<-mylist[-i]
}
else{
mylist<-myslit
}}

然而,它似乎只删除了 data.frame d。运行 for 循环后,数据框 c 仍在“mylist”中。

4

5 回答 5

13

您可以使用应用循环更轻松地做到这一点:

row_lt2 <- which(sapply(mylist, nrow) < 2)
mylist[-row_lt2]
[[1]]
  x y
1 1 m
2 2 n
3 3 o
4 4 p

[[2]]
  x y
1 2 q
2 3 w
3 4 e
4 5 r
5 6 t

[[3]]
  x y z
1 6 j $
2 7 k #

请注意,我使用负索引来删除项目而不是选择它们。

于 2013-04-23T19:25:06.717 回答
10

添加到其他答案:这正是高阶Filter函数的用途:

> Filter(function(x) {nrow(x) >= 2}, mylist)
[[1]]
  x y
1 1 m
2 2 n
3 3 o
4 4 p

[[2]]
  x y
1 2 q
2 3 w
3 4 e
4 5 r
5 6 t

[[3]]
  x y z
1 6 j $
2 7 k #
于 2013-04-23T21:00:36.823 回答
4

您无法使用此过程执行此过程,for因为索引会更改。使用for, 删除第 2 行后,您将检查第 3 行,但您需要再次检查第 2 行(因为第 2 行与之前的行不同)。将其更改为repeatwhile

a<-data.frame(x=c(1:4),y=c("m", "n", "o", "p"))
b<-data.frame(x=c(2:6),y=c("q", "w", "e", "r", "t"))
c<-data.frame(x=c(6,7),y=c("j","k"),z=c("$","#"))
d<-data.frame(x="9",y="q",z="+")
mylist<-list(a,b,c,d)

i <- 1
while (i <= length(mylist)) {
 if (nrow(mylist[[i]])<=2){
  mylist<-mylist[-i]
 }
 else{
  i <- i+1
 }
}

或者只是使用@Paul 解决方案...:P

于 2013-04-23T19:32:00.660 回答
3

保罗已经提供了答案,但没有指出你的错误。

您的代码有两个问题。首先,您需要为循环提供一个范围:

for (i in 1:length(mylist))

或 for (i in seq_along(length(mylist)))

没有这个,你的初始化看起来就像for (i in 4)在评估之后,这意味着只运行了一次迭代,删除了元素 4,甚至没有查看所有以前的元素。

但是,如果您解决了该问题,则会出现另一个问题。即,删除元素 3 后,您的列表不再有 4 个元素。它只有 3 个元素,而您的i索引会上升到 4,从而导致subscript out of bounds错误。

因此,如@Paul 所述,只能建议使用 apply 的方法。

此外,与断言相反,使用循环可以实现相同的效果for,只是您的方法需要稍有不同:

for (i in 1:length(mylist)) {
    if (nrow(mylist[[i]])>2)
    {
        mylist2[i]<-mylist[i]
    }
}  
print(mylist2)

在这里,您选择大于 2 的列表元素,并将它们分配给一个新列表。Sapply不过会更快。

于 2013-04-23T19:35:18.067 回答
0

对于一些特殊情况,上面提到的其他方法虽然while可以工作,但不起作用。我确实发现,如果您使用 Rcoster 的方法while而不添加对返回列表的评估,它仍然会返回错误的答案——因为每次评估条件时i<=length(mylist)mylist由于删除了mylist[-i]. 因此,while评估可能会在到达列表中所有不需要的元素之前停止。

例如,就我而言,我想确保mylist[[i]]<=4. 该列表非常大(从 2284879 个元素开始)。当我第一次运行while评估时,程序在取出所有内容之前停止,mylist[[i]]>4因为长度mylist变小了。我不得不用来table(lengths(mylist))判断是否所有不需要的列表都被取出了。如果没有,则while再次运行循环。幸运的是,它只运行了两次。但我认为有必要指出这一点,以防其他人来到这里并尝试使用这种while方法。

PS。for如果添加了一些评估来判断是否需要重新运行,循环应该也可以使用。

于 2018-08-12T03:51:15.127 回答