user321627
user321627

Reputation: 2564

How to check if each value in a matrix is between the corresponding values in two other matrices in R?

I have a matrix that I would like to compare with two other matrices to see if each entry in my matrix is contained within the values of the other two matrices or outside the values. For example, if my matrix is:

> M
           [,1]       [,2]       [,3]
[1,] -0.1278982  0.4600544  1.3271033
[2,] -0.1079272  1.2196851 -0.5240536 
[3,]  0.9548449 -0.9979668 -0.6636296 

and the other two matrices I have are L and U:

> L 
            [,1]      [,2]       [,3]
[1,] -0.49416022 1.0992247 -1.2834469
[2,]  0.35491793 0.2460946  1.1411529
[3,]  0.01755317 0.2469062  0.2843848

and

> U
            [,1]       [,2]        [,3]
[1,] -0.84996737  1.0036554 -0.04747612
[2,]  0.35396050 -0.4612527 -1.47341334
[3,] -0.07716839 -1.5921625  1.62187501

I would like to take each entry of M and compare to see if it is contained within the range made by the corresponding entry of L and U.

For example, for M[1,1], it is outside the range of -0.49416022 and -0.84996737, and so I will assign this comparison a value of 0. On the other hand, for M[2,3], the value is -0.5240536 and so is between 1.1411529 and -1.47341334, and so this comparison gets a value of 0.

Ultimately, I would like to obtain a matrix of all 0 and 1's, indicating if the entries in M were contained within corresponding values in L and U. For example, if we call this matrix M_comparisons, then:

> M_comparisons
            [,1]      [,2]       [,3]
[1,]           0         0          0
[2,]           0         0          1
[3,]           0         1          0

Does anyone have any ideas how I can do this for large matrices and possible in a very fast computational time? Thanks!

Upvotes: 4

Views: 334

Answers (2)

akrun
akrun

Reputation: 886938

Or another way is

+(M > U & M < L)

Upvotes: 1

DJack
DJack

Reputation: 4940

As simple as:

(M > U & M < L)*1

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

Or, as suggested by Rui Barradas (slightly faster):

as.integer(M > U & M < L)

Benchmark

library(microbenchmark)

microbenchmark(
  (M > U & M < L)*1,
  as.integer(M > U & M < L)
)

#Unit: microseconds
#                      expr   min    lq    mean median     uq    max neval
#       (M > U & M < L) * 1 1.278 1.469 2.15965  1.640 1.8000 38.981   100
# as.integer(M > U & M < L) 1.042 1.212 1.59757  1.384 1.5375 12.008   100

Sample data

M <- t(matrix(c(-0.1278982, 0.4600544, 1.3271033, 
                -0.1079272, 1.2196851, -0.5240536,
                 0.9548449, -0.9979668, -0.6636296), nrow = 3))
L <- t(matrix(c(-0.49416022, 1.0992247, -1.2834469, 
                 0.35491793, 0.2460946,  1.1411529, 
                 0.01755317, 0.2469062,  0.284384), nrow = 3))
U <- t(matrix(c(-0.84996737, 1.0036554, -0.04747612, 
                 0.35396050, -0.4612527, -1.47341334, 
                -0.07716839, -1.5921625, 1.6218750), nrow = 3))

Upvotes: 4

Related Questions