Reputation: 75
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
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
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