Nested lapply() in a list?

SavedByJESUS picture SavedByJESUS · Jan 4, 2014 · Viewed 10k times · Source

I have a list l, which has the following features:

  • It has 3 elements
  • Each element is a numeric vector of length 5
  • Each vector contains numbers from 1 to 5

l = list(a = c(2, 3, 1, 5, 1), b = c(4, 3, 3, 5, 2), c = c(5, 1, 3, 2, 4))

I want to do two things:

First

I want to know how many times each number occurs in the entire list and I want each result in a vector (or any form that can allow me to perform computations with the results later):

Code 1:

> a <- table(sapply(l, "["))
> x <- as.data.frame(a)
> x

  Var1   Freq
1    1   3
2    2   3
3    3   4
4    4   2
5    5   3

Is there anyway to do it without using the table() function. I would like to do it "manually". I try to do it right below.

Code 2: (I know this is not very efficient!)

x <- data.frame(
"1" <- sum(sapply(l, "[")) == 1
"2" <- sum(sapply(l, "[")) == 2
"3" <- sum(sapply(l, "[")) == 3
"4" <- sum(sapply(l, "[")) == 4
"5" <- sum(sapply(l, "[")) == 5)

I tried the following, but I did not work. I actually did not understand the result.

> sapply(l, "[") == 1:5        

     a     b     c
[1,] FALSE FALSE FALSE
[2,] FALSE FALSE FALSE
[3,] FALSE  TRUE  TRUE
[4,] FALSE FALSE FALSE
[5,] FALSE FALSE FALSE

> sum(sapply(l, "[") == 1:5)

[1] 2

Second

Now, I would like to get the number of times each number appears in the list, but now in each element $a, $b and $c. I thought about using the lapply() but I don't know how exactly. Following is what I tried, but it is inefficient just like Code 2:

lapply(l, function(x) sum(x == 1))
lapply(l, function(x) sum(x == 2))
lapply(l, function(x) sum(x == 3))
lapply(l, function(x) sum(x == 4))
lapply(l, function(x) sum(x == 5))

What I get with these 5 lines of code are 5 lists of 3 elements each containing a single numeric value. For example, the second line of code tells me how many times number 2 appears in each element of l.

Code 3:

> lapply(l, function(x) sum(x == 2))

$a
[1] 1

$b
[1] 1

$c
[1] 1

What I would like to obtain is a list with three elements containing all the information I am looking for.

Please, use the references "Code 1", "Code 2" and "Code 3" in your answers. Thank you very much.

Answer

IRTFM picture IRTFM · Jan 4, 2014

Just use as.data.frame(l) for the second part and table(unlist(l)) for the first.

> table(unlist(l))

1 2 3 4 5 
3 3 4 2 3 

> data.frame(lapply(l, tabulate))
  a b c
1 2 0 1
2 1 1 1
3 1 2 1
4 0 1 1
5 1 1 1`