0

Quite a specific question...but here it goes.

I have a vector of data indicating thermal change, and from it would like to know whether something has been switched 'ON' or 'OFF'. This something always starts 'OFF'. A threshold of +1.5 degrees indicates it has been switched 'ON', and stays on until a threshold of -1.5 degrees indicates it has been switched 'OFF' again, reaching high or low plateaus in between with much smaller +/- change. I have a numeric vector of positive and negative values that I would like to turn into a character or factor with levels 'ON' and 'OFF' in the appropriate places.

Using this:

    > Data$delta
    [1]  0.02  0.00  0.04 -0.06 -0.06 -0.02  0.01  0.31  0.22  0.21 -0.09 -0.02  0.03  0.02  0.01
    [16]  0.00  0.02  0.03  0.03  0.04  0.04  0.01  0.00  0.01  0.02  0.05  0.04  0.04  0.01  0.04
    [31]  0.02  0.01 -0.03  0.00  0.03  0.03  0.03  0.04  0.04  0.02  0.02  0.01  0.02 -0.02 -0.01
    [46] -0.03  0.01  0.03  0.37  0.14  0.04 -0.34 -0.15 -0.07  0.00  0.01  0.29  0.03  0.26 -0.12
    [61]  0.05 -0.02 -0.03  0.10 -0.11 -0.01 -0.07 -0.03 -0.01  0.01  0.30  0.12  0.05 -0.25 -0.06
    [76] -0.04 -0.04 -0.07 -0.02  0.01  0.04  0.02  0.03 -0.07 -0.12 -0.18 -0.12 -0.08 -0.05 -0.04
    [91]  0.34  2.99  4.29  5.00  1.83 -0.51 -1.63 -0.33  2.62 -0.38

I create an empty vector to receive the for() loop output and insert 'OFF' as switch is always starting with 'OFF'

    > Data$switch<- as.character(NA)
    > Data$switch<-as.character(c("OFF",Data$switch[2:(length(Data$switch))]))
    > head(Data$switch
    [1] "OFF" NA    NA    NA    NA    NA

I then create my nested ifelse() for() loop, accounting for the fact row 1 of Data$switch is already complete...

    > for(i in (2:(length(Data$delta))))
    {  ifelse(Data$switch[1:((length(Data$switch))-1)] == "OFF", 
       (ifelse (Data$delta[i] < 1.5 , Data$switch[i] <- "OFF", Data$switch[i] <- "ON" )),
       (ifelse (Data$delta[i] > {-1.5} , Data$switch[i] <- "ON", Data$switch[i] <- "OFF")))
    }

Which returns...

> Data$switch
[1] "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF"
[16] "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF"
[31] "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF"
[46] "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF"
[61] "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF"
[76] "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF" "OFF"
[91] "OFF" "ON"  "ON"  "ON"  "ON"  "ON"  "OFF" "ON"  "ON"  "ON"

Which all appears fine...apart from value 98, which should not have switched to 'ON' with delta only '-0.33'. On a larger data set these seem to be regular false change from OFF to ON at values <1.5? I've tried the syntax again in multiple forms but these are worse not better. Can anyone help identify the problem please? Data$delta is a numeric vector.

2
  • values 97 and 98 have a flag : -1.63 *-0.33* and will be seen as characters. I don't see a as.numeric in your code, but it will set these values to NA. Commented Jun 10, 2014 at 14:25
  • @Henk ...sorry the flag is not a flag, I was trying to put value 98 in bold font to illustrate the point. I will change this Commented Jun 10, 2014 at 14:34

2 Answers 2

1

OK. Here are your delta values in a more copy/paste friendly format

delta <- c(0.02, 0, 0.04, -0.06, -0.06, -0.02, 0.01, 0.31, 0.22, 0.21, 
-0.09, -0.02, 0.03, 0.02, 0.01, 0, 0.02, 0.03, 0.03, 0.04, 0.04, 
0.01, 0, 0.01, 0.02, 0.05, 0.04, 0.04, 0.01, 0.04, 0.02, 0.01, 
-0.03, 0, 0.03, 0.03, 0.03, 0.04, 0.04, 0.02, 0.02, 0.01, 0.02, 
-0.02, -0.01, -0.03, 0.01, 0.03, 0.37, 0.14, 0.04, -0.34, -0.15, 
-0.07, 0, 0.01, 0.29, 0.03, 0.26, -0.12, 0.05, -0.02, -0.03, 
0.1, -0.11, -0.01, -0.07, -0.03, -0.01, 0.01, 0.3, 0.12, 0.05, 
-0.25, -0.06, -0.04, -0.04, -0.07, -0.02, 0.01, 0.04, 0.02, 0.03, 
-0.07, -0.12, -0.18, -0.12, -0.08, -0.05, -0.04, 0.34, 2.99, 
4.29, 5, 1.83, -0.51, -1.63, -0.33, 2.62, -0.38)

Here's one way to get the data you want. First, I track when "on" and "off" flags occur and set the initial flag to off (off=1, on=2)

flags <- ifelse(delta< -1.5, 1, ifelse(delta>1.5, 2, NA))
flags[1]<-1

Now this vector has a lot of missing values. What i need to do is just carry the last value forward. I'll do that with

state <- Reduce(function(a,b) {ifelse(is.na(b),a,b)}, flags, accumulate=T)
c("OFF","ON")[state]
Sign up to request clarification or add additional context in comments.

1 Comment

+1 for Reduce but, since you end up in Reduce, avoiding ifelses with something like Reduce(function(i1, i2) {if(i2 >= 1.5) return("ON"); if(i2 <= -1.5) return("OFF"); return(i1)}, c("OFF", as.list(delta[-1])), acc = T) looks valid, unless I'm missing something.
0
    > for(i in (2:(length(Data$delta))))
{  ifelse(Data$switch[i-1] == "OFF", 
   (ifelse (Data$delta[i] < 1.5 , Data$switch[i] <- "OFF", Data$switch[i] <- "ON" )),
   (ifelse (Data$delta[i] > {-1.5} , Data$switch[i] <- "ON", Data$switch[i] <- "OFF")))
}

I believe I solved the problem! Thanks for other solutions people

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.