Reputation: 11
I've got a first vector, let's say x that consists only of 1's and -1's. Then, I have a second vector y that consists of 1's, -1's, and zeros. Now, I'd like to create a vector z that contains in index i a 1 if x[i]
equals 1 and a 1 exists within the vector y between the n precedent elements (y[(i-n):i])
...
more formally: z <- ifelse(x == 1 && 1 %in% y[(index(y)-n):index(y)],1,0)
I'm looking to create such a vector in R without looping or recursion. The proposition above does not work since it does not recognize to take the expression y[(index(y)-n):index(y)]
element by element.
Thanks a lot for your support
Upvotes: 1
Views: 1011
Reputation: 25327
Here's an approach that uses the cumsum
function to test for the number of ones that have been seen so far. If the number of ones at position i
is larger than the number of ones at position i-n
, then the condition on the right will be satisfied.
## Generate some random y's.
> y <- sample(-1:1, 25, replace=T)
> y
[1] 0 1 -1 -1 -1 -1 -1 1 -1 -1 -1 -1 0 0 -1 -1 -1 1 -1 1 1 0 0 0 1
> n <- 3
## Compute number of ones seen at each position.
> cs <- cumsum(ifelse(y == 1, 1, 0))
> lagged.cs <- c(rep(0, n), cs[1:(length(cs)-n)])
> (cs - lagged.cs) > 0
[1] FALSE TRUE TRUE TRUE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE
[13] FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE FALSE
[25] TRUE
Upvotes: 3
Reputation: 51640
You could use apply
like this, although it is essentially a pretty way to do a loop, I'm not sure if it will be faster (it may or may not).
y1 <- unlist(lapply(1:length(x), function(i){1 %in% y[max(0, (i-n)):i]}))
z <- as.numeric(x==1) * as.numeric(y1)
Upvotes: 1