2

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')
jasp singh
  • 75
  • 9
  • 1
    Please use `dput` to show the data – akrun Apr 16 '16 at 06:53
  • @akrun dput of my list is 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())) – jasp singh Apr 16 '16 at 07:20
  • The dupe link gives a way to remove the NULL. – akrun Apr 16 '16 at 07:31
  • Posted a solution below – akrun Apr 16 '16 at 07:53
  • @akrun thanks for the solution. If want the same in the list of of dataframes then by using rbind on each index of list i failed to achieve dataframe. Have edited my question – jasp singh Apr 16 '16 at 10:06
  • @akrun thnks for providing the solution. Adding little more to your answer for getting the list of dataframes i have added one line into your answer. All credits goes to you. Thanks. – jasp singh Apr 16 '16 at 10:18
  • No problem. You can edit the answer. – akrun Apr 16 '16 at 10:20

2 Answers2

1

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'])
Community
  • 1
  • 1
akrun
  • 874,273
  • 37
  • 540
  • 662
1

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
bgoldst
  • 34,190
  • 6
  • 38
  • 64