Reputation: 77
I'm trying to create a variable that holds a value and that is reset when it reaches another predefined values.
For instance. I have some data stored in a vector. In another vector (Result) I want to set the value to -1 when the value in x <= -.50 until x > 0. Same thing if x is >= .50 set value to 1 until x < 0.
x <- c(-.28 , -.32, -.38, -.49, -.52, -.44, -.33, -.28, -.16, 0, .18, .22, .33, .42, .52, .32, .26, 0, -.10, -.15)
Result <- c(0, 0, 0, 0, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0 , 1, 1, 1, 0, 0 ,0)
Comb <- data.frame(x, Result)
I can evaluate these conditions individually but I can't figure out how to set a conditional flag that's reset-able.
Thanks
Mike
Upvotes: 3
Views: 879
Reputation: 35314
Here's an Rcpp solution:
library(Rcpp);
cppFunction('
IntegerVector hysteresisRangeFlagWithReset(DoubleVector x,double low,double high,double reset) {
IntegerVector res(x.size());
if (x.size()==0) return res;
res[0] = x[0]<=low ? -1 : x[0] >= high ? 1 : 0;
for (int i = 1; i < x.size(); ++i)
res[i] =
x[i]<=low ? -1 :
x[i]>=high ? 1 :
x[i-1]<reset && x[i]>=reset || x[i-1]>reset && x[i]<=reset ? 0 :
res[i-1]
;
return res;
}
');
hysteresisRangeFlagWithReset(x,-0.5,0.5,0)
## [1] 0 0 0 0 -1 -1 -1 -1 -1 0 0 0 0 0 1 1 1 0 0 0
Data
x <- c(-0.28,-0.32,-0.38,-0.49,-0.52,-0.44,-0.33,-0.28,-0.16,0,0.18,0.22,0.33,0.42,0.52,0.32,
0.26,0,-0.10,-0.15);
Upvotes: 1
Reputation: 214927
Here is a vectorized approach using na.locf
from zoo
package. Since the result only changes values at positions where the absolute value is larger than 0.5 or the value is switching sign, we can find out these positions, fill with corresponding values and fill forward using the na.locf
function supposing we are starting from a vector of NAs
:
library(magrittr); library(zoo)
# start from a vector of NA of the same length of the vector
rep(NA, length(x)) %>%
# place 0 at positions wherever there is a sign change
replace(c(T, diff(sign(x)) != 0), 0) %>%
# place +1 or -1 at positions wherever the absolute value is larger than 0.5
replace(abs(x) >= 0.5, sign(x[abs(x) >= 0.5])) %>%
# fill the NA with the previous values -1, 0 or 1
na.locf()
# [1] 0 0 0 0 -1 -1 -1 -1 -1 0 0 0 0 0 1 1 1 0 0 0
Upvotes: 3
Reputation: 23214
x <- c(-.28 , -.32, -.38, -.49, -.52, -.44, -.33, -.28, -.16, 0, .18, .22, .33, .42, .52, .32, .26, 0, -.10, -.15)
Result <- c(0, 0, 0, 0, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0 , 1, 1, 1, 0, 0 ,0)
Comb <- data.frame(x, Result)
for(i in 1:nrow(Comb)){
if(Comb$x[i] <= -.5){
Comb$Result[i:nrow(Comb)] <- -1
}
if(Comb$x[i] >= .5){
Comb$Result[i:nrow(Comb)] <- 1
}
if(i > 1){
if(Comb$Result[i-1] == 1 & Comb$x[i] < 0 & Comb$x[i] > -.5){
Comb$Result[i:nrow(Comb)] <- 0
}
}
if(i > 1){
if(Comb$Result[i-1] == -1 & Comb$x[i] > 0 & Comb$x[i] < .5){
Comb$Result[i:nrow(Comb)] <- 0
}
}
if(Comb$x[i]==0){
Comb$Result[i] <- 0 # Based on the example data, not the narrative
}
if(i > 1){
if(Comb$Result[i-1] == 0 & Comb$x[i] < .5 & Comb$x[i] > -.5){
Comb$Result[i] <- 0
}
}
}
identical(Comb$Result, Result)
TRUE
Upvotes: 3