I have a list of data frames, and would like to remove those with less than 2 rows off from mylist:
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
}}
However it only seemed to remove data.frame d. Data frame c is still in "mylist" after running the for loop.
remove and rm can be used to remove objects. These can be specified successively as character strings, or in the character vector list , or through a combination of both. All objects thus specified will be removed. If envir is NULL then the the currently active environment is searched first.
To delete an item at specific index from R Vector, pass the negated index as a vector in square brackets after the vector. We can also delete multiple items from a vector, based on index.
You can do this more easily using an apply loop:
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 #
Notice I use negative indexing to remove items instead of selecting them.
To add to the other answers: this is exactly the type of thing the higher-order Filter
function is made for:
> 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 #
You can't do this procedure using for
because the indices change. Using for
, after removing line 2, you will examine line 3, but you need examine line 2 again (because the line 2 isn't more the same line as before). Change it to repeat
or 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
}
}
Or just use @Paul solution... :P
Paul has provided an answer already, but your mistake has not been pointed out.
Your code has two problems. First, you need to supply a range to your loop:
for (i in 1:length(mylist))
or for (i in seq_along(length(mylist)))
Without this, your initialization looked like for (i in 4)
after evaluation, meaning that only one iteration was run, removing element 4 and not even looking at all previous elements.
However, if you fix that problem, another one emerges. Namely, your list no longer has 4 elements after removing element 3. It only has 3 elements, while your i
index will go up until 4, resulting in subscript out of bounds
error.
Therefore one can only suggest the approach using apply, as described by @Paul.
Also, opposed to the assertion otherwise, it is possible to achieve the same using for
loop, only your approach needs to be slightly different:
for (i in 1:length(mylist)) {
if (nrow(mylist[[i]])>2)
{
mylist2[i]<-mylist[i]
}
}
print(mylist2)
Here you select list elements that are greater than 2, and assign them to a new list. Sapply
will be more speedy though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With