3

I need to find consecutive values in a data.frame of wind speed measurements that are smaller than a certain threshold. I'm looking for 2 consecutive observations beneath the threshold. I want to return the location of the first observation of the series that meets these criteria.

Zoe
  • 27,060
  • 21
  • 118
  • 148
ChrM
  • 61
  • 3
  • 12
  • 4
    Please provide some sample data via `dput(dataframe_name)`. See: http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example/5963610 – coatless May 10 '16 at 14:28

1 Answers1

2

The following should work for what you are asking for:

# create random vector, for example
set.seed(1234)
temp <- rnorm(50)

# get position of all observations that fulfill criterion, here obs is > 0.2
thresholdObs <- which(temp > .2)

Here, which returns the position of all observations fulfilling some criterion. At this point, it is prudent to test that there are any observations that satisfy your critieron. This can be achieved with the intersect function or subsetting together with the %in% operator:

length(intersect(thresholdObs, thresholdObs + 1))

or

length(thresholdObs[thresholdObs %in% (thresholdObs + 1L)])

If length 0 is returned, then no such observation is in your data. If length is 1 or greate, then you can use

# get the answer
min(thresholdObs[thresholdObs %in% (thresholdObs + 1L)] - 1)

or

min(intersect(thresholdObs, thresholdObs + 1))-1

As @Frank notes below, if min is fed a vector of length 0, it returns Inf, which means infinity in R. I increment these positions thresholdObs + 1 and the take the intersection of these two sets. The only positions that are returned are those where the previous position passes the threshold test. I then substract 1 from these positions and take the minimum to get the desired result. Because which will return an ordered result, the following will also work:

intersect(thresholdObs, thresholdObs + 1)[1] - 1

where [1] extracts the first element in the intersection.

Also note that

intersect(thresholdObs, thresholdObs + 1) - 1

or

thresholdObs[thresholdObs %in% (thresholdObs + 1L)]

will return all positions where there are at least two consecutive elements that pass the threshold. However, there will be multiple positions returned for consecutive values passing the threshold that are greater than 2.

lmo
  • 37,904
  • 9
  • 56
  • 69
  • Your example data gives Inf because the intersection is empty and that's what `min(numeric(0))` gives. Safer / simpler might be `w = which(temp > .5); w[ w %in% (w + 1L) ]` – Frank May 10 '16 at 15:03
  • @Frank That seems like a safer option. – lmo May 10 '16 at 15:06