Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rlist: recursively filter out list nodes with NA

Tags:

r

Using (preferably) rlist package, is there a way to filter out nodes of the (multi-level) list, so that the resulting list holds no NA values on any level?

library(rlist)
devs <- 
  list(
    p1=list(name="Ken",age=24,
      interest=c("reading","music","movies"),
      lang=list(r=NA,csharp=4)),                      # <------ NA here
    p2=list(name="James",age=25,
      interest=c("sports","music"),
      lang=list(r=3,java=2,cpp=5)),
    p3=list(name="Penny",age=NA,                      # <------ NA here
      interest=c("movies","reading"),
      lang=list(r=1,cpp=4,python=2)))

In the above example, since p1 and p3 nodes contain NA somewhere in their hierarchy, the expected output list should be p2 only. We don't know in advance the structure or names of the input list.

like image 640
Daniel Krizian Avatar asked Oct 14 '14 13:10

Daniel Krizian


2 Answers

How about:

# for every element in devs, does it have 0 NA elements when unlisted?
sapply(devs, function(x) !anyNA(unlist(x)))

which returns:

p1    p2   p3 
FALSE TRUE FALSE 

You can get just the desired list element(s) with:

devs[sapply(devs, function(x) !anyNA(unlist(x)))]
like image 61
arvi1000 Avatar answered Nov 08 '22 21:11

arvi1000


list.search() scans the list recursively on a condition and can be used to find NAs in child elements of devs.

Using pipeR and rlist together to make the code clearer:

devs %>>% 
  list.filter(. %>>% 
      list.search(anyNA(.)) %>>% 
      length == 0L)

This singles out p2 only.

This is almost a direct translation of your request :)

or an easier way is

list.filter(devs, !anyNA(unlist(.)))
like image 25
Kun Ren Avatar answered Nov 08 '22 22:11

Kun Ren