2013-04-23 16 views
5

ich eine Liste von Datenrahmen haben, und möchten mit weniger als 2 Reihen von mylist weg entfernen:R Objekte aus einer Liste mit entfernen, wenn else-Anweisung

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

aber es schien nur Daten zu entfernen .rahmen d. Der Datenrahmen c befindet sich nach dem Ausführen der for-Schleife immer noch in "mylist".

+0

+1 zu zeigen, was Sie bereits versucht, und zum Bereitstellen eines Arbeitsbeispieles. –

Antwort

8

Sie können dies tun, einfach eine Anwendung Schleife:

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 # 

Hinweis Ich verwende negative Indizierung Elemente zu entfernen, anstatt sie zu wählen.

+0

Vielen Dank. Es hat wunderbar funktioniert. : D – lamushidi

+0

Ich liebe wirklich die Ausdruckskraft dieser funktionalen Lösung zugunsten eines zwingenderen Stils mit einer for-Schleife. Es ist viel kürzer, meiner Meinung nach verständlicher. –

+0

@PaulHiemstra Ich stimme der Ausdruckskraft des funktionalen Stils zu. Dies kann mit der Funktion "Filter" sogar kurz erklärt werden. (Siehe meine Antwort unten.) –

3

Sie können diese Prozedur nicht for verwenden, da der Indizes ändern. Mit for nach Linie 2 entfernt, werden Sie Linie 3 untersuchen, aber Sie untersuchen müssen Linie 2 wieder (da die Linie 2 ist nach wie vor nicht mehr die gleiche Linie). Ändern Sie ihn auf repeat oder while.

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

Oder benutzen Sie einfach @ Paul Lösung ...: P

+0

Ich habe nur den Vorschlag des OP übersprungen, aber Sie sind völlig richtig, dass eine for-Schleife hier nicht wirklich nützlich ist. –

+1

@PaulHiemstra sapply wird immer überlegen sein, aber 'for' kann auch verwendet werden, siehe meine Antwort –

+0

Obwohl Sie ein bisschen einen anderen Ansatz als das OP nehmen, erstellen Sie ein neues ohne die Streichhölzer, anstatt die Streichhölzer zu löschen Die Liste. –

3

Paul eine Antwort bereits zur Verfügung gestellt hat, aber Ihr Fehler wurde nicht hingewiesen.

Ihr Code hat zwei Probleme. Zuerst müssen Sie einen Bereich der Schleife liefern:

for (i in 1:length(mylist)) 

oder für (i in seq_along (Länge (mylist)))

Ohne diese Ihre Initialisierung sah aus wie for (i in 4) nach der Auswertung, was bedeutet, dass Es wurde nur eine Iteration ausgeführt, wobei Element 4 entfernt wurde und nicht einmal alle vorherigen Elemente betrachtet wurden.

Wenn Sie jedoch dieses Problem zu beheben, ergibt sich eine andere. Das heißt, die Liste nicht mehr 4 Elemente nach Elemente zu entfernen 3. Es hat nur drei Elemente, während i Index bis 4 steigen wird, in subscript out of bounds Fehlern führt.

Deshalb kann man nur den Ansatz vorschlagen, mit anwenden, wie von @ Paul beschrieben.

Auch im Gegensatz zu der Behauptung, sonst ist es möglich, das gleiche mit for Schleife zu erreichen, nur Ihr Ansatz etwas anders sein muss: Sie

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

Hier Listenelemente auswählen, die größer als 2 sind, und weisen Sie sie einer neuen Liste zu. Sapply wird jedoch schneller sein.

+0

+1 schöne Lösung mit einer 'for' Schleife. Wenn 'mylist' groß ist, können Sie es zuerst im Voraus zuweisen, was viel Speicher und Zeit spart. –

+0

@PaulHiemstra Ich sehe nicht, wie man hier die Größe von mylist2 angeben könnte, außer mit Ihrem Ansatz, der die ganze Schleife überflüssig macht. –

+0

Danke für den Hinweis auf den Unterschied zwischen '(i in Länge (mylist))' ' und '(i in 1: Länge (mylist))'. Ein häufiger Fehler, den ich oft gemacht habe. – lamushidi

4

zu den anderen Antworten hinzuzufügen: Das ist genau die Art von Sache, die höheren Ordnung Filter Funktion gemacht wird:

> 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, ** Filter ** Funktion ist genial. Vielen Dank!!! – lamushidi

+0

@lamushidi Kein Problem. Sehen Sie sich die anderen Funktionen an, die auf der gleichen Hilfeseite wie "Filter" zur Verfügung stehen. Sie können sehr nützlich sein. –

Verwandte Themen