cubil
cubil

Reputation: 131

count items in list of lists

I have a list (ll) of lists (l1,l2,l3) that have the same length.

l1 <- list( c("a","b","c") , c("d","e","f") , c(NULL) )
l2 <- list( c("a","b") , c("d","e") , c(NULL) )
l3 <- list( c("a") , c("d") , c("g") ) 
ll <- list(l1,l2,l3)
str(ll)
List of 3
 $ :List of 3
  ..$ : chr [1:3] "a" "b" "c"
  ..$ : chr [1:3] "d" "e" "f"
  ..$ : NULL
 $ :List of 3
  ..$ : chr [1:2] "a" "b"
  ..$ : chr [1:2] "d" "e"
  ..$ : NULL
 $ :List of 3
  ..$ : chr "a"
  ..$ : chr "d"
  ..$ : chr "g"

is there a way to create a (summary?) table that counts/compares how many items are in each list, whitout using for/loop?

i'm thinking of an output like this:

list 1 2 3
l1 3 3 0
l2 2 2 0
l3 1 1 1

Upvotes: 4

Views: 3428

Answers (4)

milan
milan

Reputation: 4970

Another option. rapply counts the number of elements in the lists within the list. If you are fine with having these counts in a list, you could go with ll2 as your final result. The stri_list2matrix function can be used to convert the data into a matrix. We specify that empty lists get a value zero.

ll2 <- rapply(ll, length, how="list")
ll2

[[1]]
[[1]][[1]]
[1] 3

[[1]][[2]]
[1] 3

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


[[2]]
[[2]][[1]]
[1] 2

[[2]][[2]]
[1] 2

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


[[3]]
[[3]][[1]]
[1] 1

[[3]][[2]]
[1] 1

[[3]][[3]]
[1] 1

library(stringi)
stri_list2matrix(lapply(ll2, unlist), byrow=TRUE, fill=0)

     [,1] [,2] [,3]
[1,] "3"  "3"  "0" 
[2,] "2"  "2"  "0" 
[3,] "1"  "1"  "1" 

Upvotes: 3

akrun
akrun

Reputation: 887118

We can use lengths with lapply

do.call(rbind, lapply(ll, lengths))
#     [,1] [,2] [,3]
#[1,]    3    3    0
#[2,]    2    2    0
#[3,]    1    1    1

Or with lengths on simplify2array

lengths(simplify2array(ll))
#      [,1] [,2] [,3]
#[1,]    3    2    1
#[2,]    3    2    1
#[3,]    0    0    1

Taking the transpose gets the expected output

Upvotes: 6

Raja
Raja

Reputation: 167

Try this:

ll <- list(l1 = l1,l2 = l2,l3 = l3)
as.data.frame(sapply(ll, function(x){sapply(x, length)}, USE.NAMES = T))

#   l1 l2 l3
# 1  3  2  1
# 2  3  2  1
# 3  0  0  1

Upvotes: 1

Daniel
Daniel

Reputation: 2239

you could try:

t(sapply(ll, function(x) lapply(x,length)))

#    [,1] [,2] [,3]
#[1,] 3    3    0   
#[2,] 2    2    0   
#[3,] 1    1    1   

Edit:

as pointed out by @Ryan in the comments, the following simplifies it:

t(sapply(ll, lengths))

Upvotes: 5

Related Questions