0
votes

I'm new to R, trying to conditionally plot vertical bars in a line graph. I'm working with base R graphics.
The data frame where I am fetching the data from is called RW1 and I have plotted two variables of RW1 on two y-axis in the same plot. There are 2718 observations.
Now, I would like to add greyish shaded bars, arranged vertically that depend on the standard deviation of "RW1$Measured_CH1_CTT". This variable is plotted on the left y axis (side 2). Namely, whenever the standard deviation in eight consecutive observations is equal to or lower than 0.5, then a vertical bar shall be plotted for these observations.
I'm trying to write this with a for loop and embedded if statement but struggle a bit doing so. Here's what I got so far.

# Set values outside loop
xi <- 0
xj <- 0
n <- nrow(RW1)

# Run the loop
for (i in 1:n) {
  for (j in min(i+8, n-i))
    Measured_CH1_CTT = RW1$Measured_CH1_CTT[i:(i+j)]

  if (sd(Measured_CH1_CTT <= 0.5)) {
      xi <- i
      xj <- j
      rect(xleft = xi, xright = xj, ybottom = -0.6, ytop = 0.6, density = 100, col = "grey")
    }
}

Critical points are

  • the defintion of the endpoint of each interval (j); j should be eight observations from each starting point i but I have to prevent that the eight observations long interval "tips over the end" of my n. That becomes of interest at n = 2718-7=2711
  • the definition of xleft and xright, that being the start and end point of each interval, respectively, which satisfies the if condition of a standard deviation of "Measured_CH1_CTT" of equal to or less than 0.5
  • the if statement. R gives me the error "argument is not interpretable as logical"
  • ytop and ybottom: which y axis is to be specified since I have two? I was just guessing it's the left one (side 2) and indicated the range of that axis

Cheers for any suggestions!

EDIT: Since there are missing values in the variable, I specified the na.rm argument inside parantheses and placed the 'lower than equal to' expression correctly: if (sd(Measured_CH1_CTT, na.rm = TRUE) <= 0.5). That yields another error for the if statement missing value where TRUE/FALSE needed.
The crux has to be somewhere in the definition of the interval and/or the assignment of xi and xj. I executed the if() function independently (with another, simple expression) and it works. Likewise, the rect() function works when I manually specify xleft and xright.

1
It looks like the parentheses are wrong on your if statement. I think that you want if (sd(Measured_CH1_CTT) <= 0.5) - G5W
Yeh, just realized that seconds ago. Tried to run it but R gives me another error "missing value where TRUE/FALSE needed" - Arne Brandschwede
Maybe I have to specify an else statement. In case the if condition is not satisfied it abandons the loop. Did so with else{next} but I still get the same error missing value where TRUE/FALSE needed - Arne Brandschwede

1 Answers

0
votes

Okay, it took me a while but I figured it out with some help. The general problem was the defintion of the interval with i and j. A nested loop is not needed. The rect() function was specified correctly as I already assumed. I had to add !is.na(sd_temp) to the if() statement.

The correct syntax looks like the following (names adjusted to a more general understanding):

# Add vertical shaded bars
n <- nrow(df) - 7
for (i in 1:n) {
  j = i + 7 
  y_temp = df$y[i:j]

  sd_temp <- sd(y_temp, na.rm = TRUE)
  if (!is.na(sd_temp) & sd_temp <= 0.5) {
    rect(xleft = i, xright = j, ybottom = min.length_y, ytop = max.length_y, density = NA, col = "gray94")
  } else {
    next
  }
}

Maybe this is of help to someone else.

WARNING: Loops in general are somewhat slow in R. Although this particular loop had only 2700 iterations to make, the processing was extremely (!) slow and I had to abort it after 20 minutes. I assume R struggles even more when a loop is combined with a drawing function like in this case.