lionup
lionup

Reputation: 65

Compare a vector with selected element from a matrix

I want to compare a huge vector with selected element from a matrix in R.

A is a matrix and B is a vector. I want to compare each element of B with selected element from A. C and D are selection criteria. They are vectors of same length as B. C specifies the row number of A, and D specifies the column number. A is of dimension 10*100, and B,C,D are all vectors of length 72000. Code with for loop:

for ( j in 1:length(B) ){
  E[j] <- B[j] >= A[ C[j], D[j] ]
} 

This is too slow. I vectorize this by define a vector including elements from A first:

A1 <- array(0, length(B))
A2 <- A[,D]
for ( j in 1:length(B) ){
  A1[j] <- A2[ C[j], j ]
}   
E <- B >= A1

This is still too slow. Is there a better way to this?

Upvotes: 1

Views: 1830

Answers (3)

Simon O&#39;Hanlon
Simon O&#39;Hanlon

Reputation: 59980

The absolute fastest way I can think of is to treat A as a vector and extract the elements you want. A matrix is really just a vector with dimension attributes. Arithmetic operations are extremely fast and the [ subsetting operator is vectorised.

To get the desired elements all you need to do is multiply your desired column number (D) by the total number of rows and then subtract the desired row number (C) minus total number of rows, eg A[ D * nrow(A) - ( nrow(A) - C) ] as in this example:

set.seed(1234)
A <- matrix( sample(5,16,repl=TRUE) , 4 )
#    [,1] [,2] [,3] [,4]
#[1,]    2    1    1    5
#[2,]    1    3    5    5
#[3,]    2    1    1    2
#[4,]    1    4    2    1

## Rows
C <- sample( nrow(A) , 3 , repl = TRUE )
#[1] 1 2 3

## Columns
D <- sample( ncol(A) , 3 , repl = TRUE )
#[1] 1 3 2

## Treat A as a vector
## Elements are given by:
rs <- nrow(A)
A[ D * rs - ( rs - C) ]
#[1] 2 5 1

Upvotes: 1

MatthewS
MatthewS

Reputation: 536

You can easily select each element of A that corresponds to each entry of B, based on the selection criteria B and C. Combine B and C into a two-column matrix, and then subset A with that matrix:

A.subset <- A[cbind(B, C)]

You now have a vector (A.subset) of the same length as B, and can perform whatever (vectorized) comparison you like in a performant manner.

Upvotes: 2

Thomas
Thomas

Reputation: 44555

I'm not sure I totally get your question, but I think you want something like the following:

# setup some mock data
a <- matrix(rnorm(1000,0,1),nrow=10, ncol=100)
b <- rnorm(100,0,1)
c <- rep(1:10,10)
d <- 1:100

# define function
compare <- function(v,row,column)
    return(v >= a[row,column]) # you might want this to output to something else

# apply the comparison function to the b, c, and d vectors
mapply(FUN=compare, b, c, d)

Upvotes: 0

Related Questions