2013-04-23 124 views
5

我有數據幀的列表中刪除的對象,並願與少於2排開來MYLIST刪除那些:[R從清單,如果else語句

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 
}} 

但是它似乎只刪除數據.frame d。運行for循環後,數據幀c仍處於「mylist」狀態。

+0

+1用於顯示你已經嘗試過,並提供一個工作的例子。 – 2013-04-23 19:44:04

回答

8

您可以使用應用循環更容易做到這一點:

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 # 

通知我用負索引刪除的項目,而不是選擇他們的。

+0

非常感謝。它製作得很漂亮。 :D – lamushidi 2013-04-23 19:39:51

+0

我真的很喜歡這個功能性解決方案的表現力,並贊成使用for循環的更強制性的風格。它短得多,在我看來更容易理解。 – 2013-04-23 20:18:07

+0

@PaulHiemstra我贊同功能風格的表現力。這可以通過'Filter'功能簡化。 (請參閱下面的答案。) – 2013-04-23 21:04:02

3

你不能這樣做使用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 
} 
} 

或者只是使用@保羅的解決方案...:P

+0

我剛剛跳過了OP的建議,但是你完全正確,for循環在這裏並不實用。 – 2013-04-23 19:41:59

+1

@PaulHiemstra sapply將永遠是優越的,但'for'也可以使用,請參閱我的回答 – 2013-04-23 19:56:41

+0

儘管您採取了與OP不同的方法,創建一個排除比賽的新方法,而不是刪除比賽列表。 – 2013-04-23 20:15:34

3

保羅已經給出了一個答案,但你的錯誤還沒有被指出。

您的代碼有兩個問題。首先,你需要提供一個範圍,以你的循環:

for (i in 1:length(mylist)) 

或 (我在seq_along(長度(MYLIST)))

不這樣做,你的初始化看起來像for (i in 4)評估後,這意味着只運行了一次迭代,刪除了元素4,甚至沒有查看所有以前的元素。

但是,如果解決這個問題,一個又一個出現。也就是說,你的列表中不再具有去除部件3後4種元素它只有3個元素,而你的i指數將上升到4,導致subscript out of bounds錯誤。

因此,我們可以使用應用,如通過@保羅描述僅建議的辦法。

此外,反對斷言,否則,有可能達到相同的使用for循環,只有你的方法需要略有不同:

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

在這裏,你選擇是大於2列表元素,並將它們分配到一個新的列表。 Sapply雖然會更快。

+0

+1使用'for'循環的很好的解決方案。如果'mylist'很大,你可以先預先分配它,節省大量的內存和時間。 – 2013-04-23 20:16:19

+0

@PaulHiemstra我看不出如何在這裏指定mylist2的大小,除了使用你的方法,它使整個循環過時:) – 2013-04-23 20:40:21

+0

感謝您指出'(我在長度(mylist))'和'(我在1:長度(mylist))'。我經常犯的一個常見錯誤。 – lamushidi 2013-04-23 21:35:30

4

要添加到其他的答案:這正是高階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 # 
+0

WOW,**過濾器**功能非常棒。謝謝!!! – lamushidi 2013-04-23 21:30:50

+0

@lamushidi沒問題。查看與'?Filter'相同的幫助頁面上的其他功能。它們可能非常有用。 – 2013-04-24 00:53:25