StudentOfScience
StudentOfScience

Reputation: 809

R: find specific types in matrix

Say you have this matrix:

m1 = matrix(0, 5, 5, dimnames = list(c("A", "B", "C", "D", "E"), c(1, 2, 3, 4, 5)))
m1[1,] = c(0,50,-10,0,10)
m1[2,] = c(0,0,0,10,50)
m1[3,] = c(0,0,10,100,4)
m1[4,] = c(40,40,100,1,0)
m1[5,] = c(1,0,100,0,60))

And v1 is a vector of thresholds:

v1 = matrix(0, 1, 5, dimnames = list(c("thresholds", c(1, 2, 3, 4, 5)))
v1[1,] = c(10,20,10,50,90)

I want to do this in R and using vectorization rather than loops... First a function that takes any matrix:

#m is a matrix, #v is a vector of therholds
limitme <- function(x, v){
    y <- matrix(0, ncol(x), nrow(x)) #matrix of 0s same size as x
    for (i in 1:norow(x)){
        for (j in 1:nocol(x){
            if (x[i,j] >= v[j]) {
                y[i,j] = 100 #this could be whatever but I am choosing 0 and 100
                }
            elif (x[i,j] < v[j]) {
                y[i,j] = 0 #this could be whatever but I am choosing 0 and 100
                }
        }
    }
return(y)
}

Upvotes: 0

Views: 53

Answers (1)

IRTFM
IRTFM

Reputation: 263331

m1 <-structure(c(0, 0, 0, 40, 1, 50, 0, 0, 40, 0, -10, 0, 10, 100, 
100, 0, 10, 100, 1, 0, 10, 50, 4, 0, 60), .Dim = c(5L, 5L), .Dimnames = list(
    c("A", "B", "C", "D", "E"), c("1", "2", "3", "4", "5")))
v1<-structure(c(10, 20, 10, 50, 90), .Dim = c(1L, 5L), .Dimnames = list(
    "thresholds", c("1", "2", "3", "4", "5")))
#---------------------
> v1
            1  2  3  4  5
thresholds 10 20 10 50 90

You can use the sweep operator to apply a different threshold for each column:

sweep(m1, 2, v1['thresholds',], ">")
      1     2     3     4     5
A FALSE  TRUE FALSE FALSE FALSE
B FALSE FALSE FALSE FALSE FALSE
C FALSE FALSE FALSE  TRUE FALSE
D  TRUE  TRUE  TRUE FALSE FALSE
E FALSE FALSE  TRUE FALSE FALSE

And:

> sweep(m1, 2, v1['thresholds',], ">")*100
    1   2   3   4 5
A   0 100   0   0 0
B   0   0   0   0 0
C   0   0   0 100 0
D 100 100 100   0 0
E   0   0 100   0 0

You can use a matrix of logical to choose from two alternatives. (Might be more interesting, i.e. difficult, to choose between multiple intervals. Would probably need to use apply with findInterval.) Here I'm choosing between "A" and "B" but it could have been bweteen numeric values:

matrix( c("A", "B")[ 1+sweep(m1, 2, v1['thresholds',], ">") ], nrow=nrow(m1) )
     [,1] [,2] [,3] [,4] [,5]
[1,] "A"  "B"  "A"  "A"  "A" 
[2,] "A"  "A"  "A"  "A"  "A" 
[3,] "A"  "A"  "A"  "B"  "A" 
[4,] "B"  "B"  "B"  "A"  "A" 
[5,] "A"  "A"  "B"  "A"  "A" 

Upvotes: 1

Related Questions