GabrielMontenegro
GabrielMontenegro

Reputation: 762

Remove empty lists froms lists at any level in R

I have a list that have several list inside it:

> res$go
$MF
$MF[[1]]
                                 term evidence         id   pubmed
1 G-protein coupled receptor activity      IEA GO:0004930       NA
2                 calcium ion binding      IEA GO:0005509       NA
3                     protein binding      IPI GO:0005515 17474147

$MF[[2]]
NULL


$BP
$BP[[1]]
                                                             term evidence         id   pubmed
1                                                neuron migration      IEA GO:0001764       NA
2                           regulation of protein phosphorylation      IEA GO:0001932       NA
3 homophilic cell adhesion via plasma membrane adhesion molecules      IEA GO:0007156       NA
4                    G-protein coupled receptor signaling pathway      IEA GO:0007186       NA
5                                            axonal fasciculation      IEA GO:0007413       NA
6                              regulation of protein localization      IEA GO:0032880       NA
7                                                 cilium assembly      IEA GO:0042384       NA
8             Wnt signaling pathway, planar cell polarity pathway      NAS GO:0060071 24431302

$BP[[2]]
NULL


$CC
$CC[[1]]
                            term evidence         id
1                plasma membrane      IEA GO:0005886
2 integral component of membrane      IEA GO:0016021

$CC[[2]]
NULL

However, some of them have NULL lists within them. I was trying to find a way to remove empty lists at these levels from my res$go list but I couldn't.

I tried:

res$go[!is.null(res$go)]

But the results were the same, even if I try specifying a level further I can't remove them.

res$go$BP[!is.null(res$go$BP)]

Thanks for the help.

OUTPUT from dput

> dput(res$go)
structure(list(MF = list(structure(list(term = c("G-protein coupled receptor activity", 
"calcium ion binding", "protein binding"), evidence = c("IEA", 
"IEA", "IPI"), id = c("GO:0004930", "GO:0005509", "GO:0005515"
), pubmed = c(NA, NA, 17474147L)), .Names = c("term", "evidence", 
"id", "pubmed"), class = "data.frame", row.names = c(NA, 3L)), 
    NULL), BP = list(structure(list(term = c("neuron migration", 
"regulation of protein phosphorylation", "homophilic cell adhesion via plasma membrane adhesion molecules", 
"G-protein coupled receptor signaling pathway", "axonal fasciculation", 
"regulation of protein localization", "cilium assembly", "Wnt signaling pathway, planar cell polarity pathway"
), evidence = c("IEA", "IEA", "IEA", "IEA", "IEA", "IEA", "IEA", 
"NAS"), id = c("GO:0001764", "GO:0001932", "GO:0007156", "GO:0007186", 
"GO:0007413", "GO:0032880", "GO:0042384", "GO:0060071"), pubmed = c(NA, 
NA, NA, NA, NA, NA, NA, 24431302L)), .Names = c("term", "evidence", 
"id", "pubmed"), class = "data.frame", row.names = c(NA, 8L)), 
    NULL), CC = list(structure(list(term = c("plasma membrane", 
"integral component of membrane"), evidence = c("IEA", "IEA"), 
    id = c("GO:0005886", "GO:0016021")), .Names = c("term", "evidence", 
"id"), class = "data.frame", row.names = 1:2), NULL)), .Names = c("MF", 
"BP", "CC"))

Upvotes: 1

Views: 422

Answers (1)

A. Webb
A. Webb

Reputation: 26446

A useful function for your toolbox if working with recursive data structures is the walk

postwalk<-function(x,f,pred) if(pred(x)) f(lapply(x,postwalk,f,pred)) else f(x)

This can be more flexible than rapply. For your case,

postwalk(data,function(x) Filter(Negate(is.null),x), function(x) class(x)=="list")

where data is your structure, ought to work.

Upvotes: 3

Related Questions