2

I ran a loop that iterated through and created a bunch of objects whose names all start with "results_" and that are of differing nrow lengths, many of which are 0.

To make this list of objects easier to handle, I'd like to remove any objects whose nrow is equal to 0. I've tried below a variety of solutions provided for similar questions to this one, but none worked for my particular case. What am I doing wrong?

Attempt 1: rm(list=ls(all=TRUE)[sapply(mget(ls(all=TRUE)), function(x) nrow(x) == 0)])

Attempt 2: rm(list=ls()[!sapply(mget(ls(),.GlobalEnv), function(x) { nrow(x) == 0 } )])

Attempt 3:

rm(list=
    Filter(
        Negate(is.na),                                  # filter entries corresponding to objects that don't meet function criteria   
        sapply(
            ls(pattern="^results_"),                     # only objects that start with "results_"
            function(x) if(nrow(x) == 0) x else NA   # return names of objects of nrow length 0
        )))
Phil
  • 7,287
  • 3
  • 36
  • 66
  • Try `rm(list = ls(pattern = "results_")[sapply(ls(pattern = "results_"), function(x) NROW(get(x))) == 0])` – d.b Jul 12 '17 at 16:30
  • @d.b Thanks that worked! If you submit it as an answer, I'll check it. Also, I'm not clear on why `NROW` works while `nrow` didn't. – Phil Jul 12 '17 at 16:31
  • This is a typical [x/y problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem): the real issue is that you shouldn’t be creating such elements in the first place! Instead, organise your data in lists and data.frames. – Konrad Rudolph Jul 12 '17 at 17:05

2 Answers2

2

I'd go with get as it returns the object instead of putting it in a list. Try

rm(list = ls(pattern = "results_")[sapply(ls(pattern = "results_"), function(x)
                                                                    NROW(get(x))) == 0])

Example

results_1 = data.frame(x = 1:5)
results_2 = data.frame(x = numeric(0))
NROW(results_1)
#[1] 5
NROW(results_2)
#[1] 0
ls()
#[1] "results_1" "results_2"
rm(list = ls(pattern = "results_")[sapply(ls(pattern = "results_"), function(x)
                                                                    NROW(get(x))) == 0])
ls()
#[1] "results_1"
d.b
  • 32,245
  • 6
  • 36
  • 77
  • Do you know why it needed `NROW` instead of `nrow`? I'm not clear on how treating a vector as a 1-column matrix has an impact. – Phil Jul 12 '17 at 16:37
  • @Phil, `NROW` works even if there is a vector. Try `NROW(1)` vs `nrow(1)` – d.b Jul 12 '17 at 16:38
0

Concerning your problem, my suggestion would be to store all your objects inside a list and then mine this list for objects with nrow == 0. This is much easier than trying to work with variable names since ls() function returns only the names as characters and not the object in itself so you would need to find a way to call them after. Below I've posted a short toy example on how to do that with a list where the first matrix is nrow == 0. Hope this will help you. Best regards,


superList=c() #define a list to store your objects
for(i in 0:5){ #generate them and store them in your list, the first matrix has nrow = 0
  item=matrix(nrow = i,ncol=2)
  superList[[i+1]]=item
  print(i)

}
toErase=sapply(superList,function(x) nrow(x)==0)  #scan your list to find object with nrow==0
superList=superList[-which(toErase==TRUE)] #remove them from your list
sapply(superList,function(x) nrow(x)) #check that the first matrix
R-addict
  • 7
  • 5