user2205916
user2205916

Reputation: 3456

R Vectorization: How to return the index of the first element of each row in a matrix that meets a condition and sum all elements until that index?

I am looking for a vectorized solution. Say I generate 100 samples of 10 draws with replacement. Next, I want to find the first index of the first element of a matrix of cumulative sums that means some condition, say, >=10. Then, I want to sum all elements of each row up until the index of the first element meeting that condition. MWE:

set <- c(1, 5, 7, 13, 15, 17)
samp <- samp <- matrix(sample(set, size = 100*10, replace = TRUE), nrow=simCount) # generate 100 samples of 10 draws
b <- matrix(apply(samp, 1, cumsum), 
  nrow = 100, byrow=TRUE) >= 10 # compare each element with 10, return boolean

I'm not sure how to use apply with which(x)=="TRUE". I tried a few variations but I'm not sure how code it correctly.

After I get that, I'll be able to use apply(b, 1, min) to return the first element (minimum index) for each row that is >=10.

Upvotes: 1

Views: 108

Answers (2)

akrun
akrun

Reputation: 887301

We could use rowCumsums from library(matrixStats)

library(matrixStats)
apply(rowCumsums(samp)>=10, 1, which.max)

Upvotes: 2

N8TRO
N8TRO

Reputation: 3364

Set seed please for "random" examples:

set.seed(111)
samp <- matrix(sample(1:5, s=1000, r=T), nrow=100)
(answer1 <- samp[which(apply(samp,1,function(x)sum(x)>30)),1])
# [1] 4 3 3 3 1 1 3 5 2 4 2 5 4 2 4 1 3 2 4 4 5 4 2 4 5 5 4 5 3 3 1 1 2 1 4 3 4 5
#[39] 1 5 1 4 4 3 3 2 5 5

Explanation:

apply(samp,1, function(x) sum(x) > 30)
Well, if you add 10 positive integers, >=10 will ALWAYS be true. apply to "samp" for each row this function.

which(x) returns the index of all TRUE values of x. (the rows of interest)

samp[(rows returned by which), (1)st column] ... basic indexing

unwrap step by step from the outside in for better understanding.

b <- matrix(apply(samp, 1, cumsum), nrow=100, byrow=T)>=10
apply(b,1,function(x)which(x)[1])
#  [1] 4 5 4 3 3 5 3 4 3 4 3 3 5 4 5 4 2 4 3 6 3 3 5 4 3 3 2 4 4 6 3 4 3 4 5 4 4
# [38] 4 3 5 3 6 3 3 5 5 3 3 4 6 4 5 4 4 3 4 4 4 2 5 3 4 3 4 4 3 4 6 3 5 4 4 4 4
# [75] 3 3 5 4 4 3 3 4 4 5 4 4 4 3 4 3 5 4 3 5 3 6 4 5 5 3

Upvotes: 2

Related Questions