lightsnail lightsnail - 1 month ago 8
R Question

Calculate the conditional proportions in a list

j
is a list made of matrices.

j <- list(matrix(1:12,3),matrix(50:61,3))

> j
[[1]]
[,1] [,2] [,3] [,4]
[1,] 1 4 7 10
[2,] 2 5 8 11
[3,] 3 6 9 12

[[2]]
[,1] [,2] [,3] [,4]
[1,] 50 53 56 59
[2,] 51 54 57 60
[3,] 52 55 58 61


k
is also a list made of matrices.

k <- list(matrix(c(T,T,T,T,T,T,F,T,F,F,F,F),3,byrow = T),
matrix(c(T,F,T,F,F,T,T,T,F,F,F,F),3,byrow = T))

> k
[[1]]
[,1] [,2] [,3] [,4]
[1,] TRUE TRUE TRUE TRUE
[2,] TRUE TRUE FALSE TRUE
[3,] FALSE FALSE FALSE FALSE

[[2]]
[,1] [,2] [,3] [,4]
[1,] TRUE FALSE TRUE FALSE
[2,] FALSE TRUE TRUE TRUE
[3,] FALSE FALSE FALSE FALSE


j
and
k
have the same dimensions. In each row, I want to calculate the values of
j
divided by the sum of
TRUE
j
.

Let me explain it with examples:

The first row in the first object of
j
is
1 4 7 10
, and the corresponding row of
k
is
TRUE TRUE TRUE TRUE
, since all the corresponding
j
s are all true, so the sum of "True"
j
is 1+4+7+10 = 22, so the values of
j
divided by the sum of "True"
j
is
1/22 4/22 7/22 10/22
, that is
0.04545455 0.18181818 0.31818182 0.45454545
.

Another example: the second row in the first object of
j
is
2 5 8 11
, and the corresponding row of
k
is
TRUE TRUE FALSE TRUE
, so the sum of "True"
j
is 2+5+11 = 18, so the values of
j
divided by the sum of "True"
j
is
2/18 5/18 8/18 11/18
, that is
0.1111111 0.2777778 0.4444444 0.6111111
.

So the final expected result is:

[[1]]
[,1] [,2] [,3] [,4]
[1,] 0.04545455 0.18181818 0.31818182 0.45454545
[2,] 0.1111111 0.2777778 0.4444444 0.6111111
[3,] Inf Inf Inf Inf

[[2]]
[,1] [,2] [,3] [,4]
[1,] 0.4716981 0.5000000 0.5283019 0.5566038
[2,] 0.2982456 0.3157895 0.3333333 0.3508772
[3,] Inf Inf Inf Inf


I find that the
Map(function(a,b) a[b], j, k)
can extract the all the true values, but I don't know how to
sum
them row by row,

Answer

You can use Map and rowSums, Map is used to loop through j and k at the same time, and rowSums can be used to calculate the conditional sum of rows by simply multiplying matrices in j with matrices in k:

Map(function(x,y) x/rowSums(x*y), j, k)

# [[1]]
#            [,1]      [,2]      [,3]      [,4]
# [1,] 0.04545455 0.1818182 0.3181818 0.4545455
# [2,] 0.11111111 0.2777778 0.4444444 0.6111111
# [3,]        Inf       Inf       Inf       Inf
# 
# [[2]]
#           [,1]      [,2]      [,3]      [,4]
# [1,] 0.4716981 0.5000000 0.5283019 0.5566038
# [2,] 0.2982456 0.3157895 0.3333333 0.3508772
# [3,]       Inf       Inf       Inf       Inf