CAM_etal
CAM_etal

Reputation: 93

Faster way to count rows matching a value in R

My code works but it is extremely slow. What I want to do is take two vectors of equal length, examine the values row by row, and count the number of rows that are both equal 1. I want to stress that I'm not looking to sum the number of times that each vector, on its own, has the value of 1. Rather, when these vectors are lined up side by side, how many times do we see both rows equal 1?

I've accomplished this with a for loop and a if statement, where I loop through the "row pairs" and grow a variable by +1 every time there's a matching pair equaling 1. That code is below, but it's too slow. I have to perform this operation with over 2000 vectors that are at least 4e6 long.

Relatively new to R here, but if anyone has any other ideas on quicker ways, I'm grateful for any advice.

vec1 <- rep(c(0,0,1,1),times = 10)
vec2 <- rep(c(0,1,0,1),times = 10)

mat <- cbind(vec1,vec2)

matches <- 0
for(i in 1:length(mat[,1])){
  if(mat[i,1] == 1 & mat[i,2] == 1){
    matches <- matches + 1
  }
} 

Upvotes: 1

Views: 305

Answers (3)

utubun
utubun

Reputation: 4520

Working just on vectors:

sum(vec1 * vec2)
# [1] 10

sum(vec1 & vec2)
# [1] 10

sum(vec1[!!vec2])
# [1] 10

# and going mad
vec1 %*% vec2
#      [,1]
# [1,]   10

# or even
sum(Mod(complex(real = vec1, imaginary = vec2)) == sqrt(2)) #joking
# [1] 10

Upvotes: 0

Tur
Tur

Reputation: 614

Go logical and sum it, it counts TRUE and FALSE as 1 and 0 respectively

sum( (vec1 == 1) & (vec2 == 1))
#[1] 20

Upvotes: 0

Ronak Shah
Ronak Shah

Reputation: 388807

If vectors have only 1 and 0 values :

sum(rowSums(mat) == 2)
#[1] 10

If they can have different values compare it with 1 :

sum(rowSums(mat == 1) == 2)

To get row numbers where both columns have 1 we could use which :

which(rowSums(mat) == 2)
#[1]  4  8 12 16 20 24 28 32 36 40

Upvotes: 1

Related Questions