rook1996
rook1996

Reputation: 247

R: Calculation with each element in a matrix across lists

I think my example is something special. Since I am not advanced in the use of lapply I am stucking with the following calculation. Here is a short reproducivle example: Assume I've a list containing three matrices:

list <- list(est1=matrix(sample(c(0,0.4,0.2,1), replace=TRUE, size=10), ncol=2), est2=matrix(sample(c(0,0.4,0.2,1), replace=TRUE, size=10), ncol=2),
    est3=matrix(sample(c(0,0.4,0.2,1), replace=TRUE, size=10), ncol=2))

$`est1`
     [,1] [,2]
[1,]  0.4  1.0
[2,]  0.0  0.4
[3,]  0.0  0.0
[4,]  0.0  0.4
[5,]  0.0  1.0

$est2
     [,1] [,2]
[1,]  0.0  0.2
[2,]  0.4  0.4
[3,]  1.0  0.0
[4,]  0.2  1.0
[5,]  0.4  0.4

$est3
     [,1] [,2]
[1,]  1.0  0.2
[2,]  0.4  1.0
[3,]  1.0  0.0
[4,]  1.0  0.2
[5,]  0.4  0.4

Each matrix contains coefficient estimates for different iterations. Each element inside one matrix belongs to one coefficient. I want to calculate the percentage over the three Matrices at which a coefficient is different from zero.

Expected Output:

[,1] [,2]
0.67 1
0.67 1
0.67 0
0.67 1
0.67 1

Upvotes: 1

Views: 100

Answers (2)

Rui Barradas
Rui Barradas

Reputation: 76432

Maybe the following does what you want.
I start by setting the RNG seed to make the results reproducible

set.seed(2081)    # Make the results reproducible
list <- list(est1 = matrix(sample(c(0,0.4,0.2,1), replace=TRUE, size=10), ncol=2),
             est2 = matrix(sample(c(0,0.4,0.2,1), replace=TRUE, size=10), ncol=2),
             est3 = matrix(sample(c(0,0.4,0.2,1), replace=TRUE, size=10), ncol=2))

zeros <- sapply(list, `==`, 0)
res <- rowSums(zeros) / ncol(zeros)
matrix(res, ncol = 2)
#          [,1]      [,2]
#[1,] 0.3333333 0.3333333
#[2,] 0.0000000 0.6666667
#[3,] 0.0000000 0.3333333
#[4,] 0.3333333 0.3333333
#[5,] 0.6666667 0.3333333

EDIT.

The following uses rowMeans and is simpler. The result is identical() to res above.

res2 <- rowMeans(zeros)
identical(res, res2)
#[1] TRUE

matrix(res2, ncol = 2)

Upvotes: 1

Vincent Guillemot
Vincent Guillemot

Reputation: 3429

Please do not call your list list. In the following, it will be called z.

z <- list(est1=matrix(sample(c(0,0.4,0.2,1), replace=TRUE, size=10), ncol=2), est2=matrix(sample(c(0,0.4,0.2,1), replace=TRUE, size=10), ncol=2),
             est3=matrix(sample(c(0,0.4,0.2,1), replace=TRUE, size=10), ncol=2))

For the kind of problems that you describe, I like to use arrays, so the first step is to transform your list into an array.

library(abind)
A <- abind(list, along=3)

Then, you can apply a function along the third dimension:

apply(A, 1:2, function(x) 100 * sum(x!=0) / length(x))

      [,1]  [,2]
[1,] 100.0 100.0
[2,] 100.0  66.7
[3,] 100.0  66.7
[4,] 100.0  66.7
[5,]  66.7  66.7

Upvotes: 3

Related Questions