jasp singh
jasp singh

Reputation: 75

Remove null lists from the whole set of list and convert the list into a dataframe in r

I have a list and that contains elements as follow.

[[1]]
[[1]][[1]]
[[1]][[1]][[1]]
[[1]][[1]][[1]][[1]]
[1] "ip4"


[[1]][[1]][[2]]
[[1]][[1]][[2]][[1]]
[1] "ip1"

[[1]][[1]][[2]][[2]]
[1] "ip1"


[[1]][[1]][[3]]
[[1]][[1]][[3]][[1]]
[1] "ip6"

[[1]][[1]][[3]][[2]]
[1] "ip6"



[[1]][[2]]
[[1]][[2]][[1]]
[[1]][[2]][[1]][[1]]
[1] "ip4" "ip6"



[[1]][[3]]
list()


[[2]]
[[2]][[1]]
[[2]][[1]][[1]]
[[2]][[1]][[1]][[1]]
[1] "ip5"

[[2]][[1]][[1]][[2]]
[1] "ip5"



[[2]][[2]]
list()


[[3]]
[[3]][[1]]
[[3]][[1]][[1]]
[[3]][[1]][[1]][[1]]
[1] "ip10"


[[3]][[1]][[2]]
[[3]][[1]][[2]][[1]]
[1] "ip11"


[[3]][[1]][[3]]
[[3]][[1]][[3]][[1]]
[1] "ip3"

[[3]][[1]][[3]][[2]]
[1] "ip3"



[[3]][[2]]
[[3]][[2]][[1]]
[[3]][[2]][[1]][[1]]
[1] "ip11" "ip3" 



[[3]][[3]]
list()

[[3]][[4]]
list()

I want to remove the lists which contains empty list and convert this list into a dataframe. So from the above list my desired output sholud be a dataframe that contains a list of vectors in its row. Dataframe myDf should be as follows.

myDF

col
ip4
ip1
ip1
ip6
ip6
c('ip4','ip6')
ip5
ip5
ip10
ip11
ip3
ip3
c('ip11','ip3') and to have list of dataframes where i will be having



    col
[[1]]ip4
     ip1
     ip1
     ip6
     c('ip4','ip6')

      col
[[2]] ip5
      ip5

      col
[[3]] ip10
      ip11
      ip3
      ip3
     c('ip11' , 'ip3')

Upvotes: 2

Views: 126

Answers (2)

akrun
akrun

Reputation: 886948

One option would be to remove the NULL elements using the function showed here

is.NullOb <- function(x) is.null(x) | all(sapply(x, is.null))


rmNullObs <- function(x) {
x <- Filter(Negate(is.NullOb), x)
  lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x)
}

lst1 <- rmNullObs(lst)

Then melt the new list ('lst1'), and paste the 'value' elements grouped by the other columns with aggregate, subset the value column.

library(reshape2)
d1 <- aggregate(value~., melt(lst1), FUN= toString)['value']
d1
#       value
#1        ip4
#2        ip1
#3        ip1
#4        ip6
#5        ip6
#6   ip4, ip6
#7        ip5
#8        ip5
#9       ip10
#10      ip11
#11       ip3
#12       ip3
#13 ip11, ip3

For getting the list of dataframes we can use lapply.

lst_df <- lapply(lst1 ,function(x) aggregate(value~., melt(x), 
          FUN= toString)['value'])

Upvotes: 1

bgoldst
bgoldst

Reputation: 35314

A little while ago I wrote a generic function that allows transforming a recursive list, which I refer to here as a "tree", into any output object:

treeapply <- function(
    tr, ## tree
    fl=function(b,i,e) invisible(), ## leaf node function
    fi=function(b,i,e) invisible(), ## internal node function
    init=NULL, ## initial buildup object value or function
    b=if (is.function(init)) init(tr) else init ## buildup object
)
    unlist(recursive=F,lapply(seq_along(tr),function(i) {
        e <- tr[[i]];
        if (is.list(e)) treeapply(e,fl,fi,b=fi(b,i,e)) else fl(b,i,e);
    }));

With this function, we can very easily combine the leaf nodes into a list:

l <- list(list(list(list('ip4'),list('ip1','ip1'),list('ip6','ip6')),list(list(c('ip4','ip6'))),list()),list(list(list('ip5','ip5')),list()),list(list(list('ip10'),list('ip11'),list('ip3','ip3')),list(list(c('ip11','ip3'))),list(),list()));
treeapply(l,function(b,i,e) c(b,list(e)));
## [[1]]
## [1] "ip4"
##
## [[2]]
## [1] "ip1"
##
## [[3]]
## [1] "ip1"
##
## [[4]]
## [1] "ip6"
##
## [[5]]
## [1] "ip6"
##
## [[6]]
## [1] "ip4" "ip6"
##
## [[7]]
## [1] "ip5"
##
## [[8]]
## [1] "ip5"
##
## [[9]]
## [1] "ip10"
##
## [[10]]
## [1] "ip11"
##
## [[11]]
## [1] "ip3"
##
## [[12]]
## [1] "ip3"
##
## [[13]]
## [1] "ip11" "ip3"
##

From which we can make a data.frame:

data.frame(col=I(treeapply(l,function(b,i,e) c(b,list(e)))));
##          col
## 1        ip4
## 2        ip1
## 3        ip1
## 4        ip6
## 5        ip6
## 6   ip4, ip6
## 7        ip5
## 8        ip5
## 9       ip10
## 10      ip11
## 11       ip3
## 12       ip3
## 13 ip11, ip3

Upvotes: 1

Related Questions