Reputation: 559
I have x
x <- c(2, 28, 1, 31, 1, 10, 2, 1, 17, 4, 2, 5, 19, 6)
I want to find those numbers which oscillates three or more times between being the same or more than 7 followed by a 2 or 1 and convert x into 0s and 1s to reflect when this is true.
oscillates_more_than_once
[1] 0 1 0 1 0 1 0 0 0 0 0 0 0 0
For a number of 7 and above that is flanked by a 4 or less I also want to convert x into 0s and 1s to reflect when this is true.
oscillates_once
[1] 0 0 0 0 0 0 0 0 1 0 0 0 0 0
However, if the number is above 7, but is flanked by 5 or above I wish to also find it separately.
flanked
[1] 0 0 0 0 0 0 0 0 0 0 0 1 1 1
Would pattern matching be the best way to solve this?
Attempt at oscillates_more_than_once that does not work as it does not go through each element.
if (length(x[x >= 7]) > 3) {
test <- as.numeric(x >=7)
lag.test <- c(tail(test,-1),NA)
for (w in 1:length(test)) {
if (!(as.numeric(test[w]==lag.test[w])) && as.numeric(test[w]==1)) {
as.numeric(x >= 7) ###converts all of x not just those elements that oscillate
}
else {
as.numeric(!(x))
}
}
}
Upvotes: 0
Views: 54
Reputation: 70336
You could try the following:
library(dplyr) # for lead()
#1
y1 <- as.integer(x > 7 & lead(x) %in% 1:2)
#[1] 0 1 0 1 0 1 0 0 0 0 0 0 0 0
#2
y2 <- as.integer(x >= 7 & (lead(x) <= 4 | lag(x) <= 4) & !y1)
#[1] 0 0 0 0 0 0 0 0 1 0 0 0 0 0
#3
y3 <- as.integer((x >= 5 & (lead(x) > 7 | lag(x) > 7) )| (x > 7 & lead(x) >= 5 & lag(x) >= 5))
#[1] 0 0 0 0 0 0 0 0 0 0 0 1 1 1
Upvotes: 1