Question

I have data of fluxes over time and would like to obtain a list of times when the flux changed from negative to positive or vice versa. This seems like a simple thing so it probably has a simple answer but I haven't been able to find one with my search terms.

Sample data:

day=c(1,2,3,5,10,20)
flux=c(-2,-4,1,-2,4,11)

I'd like to get something like a vector crossover_times= (2.5, 4, 7.5) to indicate the interpolated days that the change occurred and, ideally, also information indicating which way the sign change went, e.g. sign_changes =(positive, negative, positive).

I could, of course, write a loop to iterate through the data but I'm guessing that R has one or more helpful functions for this. Any suggestions?

Was it helpful?

Solution

diff(sign(flux)) will be non-zero at cross-overs and will have the sign of the crossing:

updn <- c(0, diff(sign(flux)))
ix <- which(updn != 0)

(day[ix] + day[ix-1])/2
## [1] 2.5 4.0 7.5

sign(updn)[ix]
## [1]  1 -1  1

UPDATED: Added sign of crossing. Improvements.

OTHER TIPS

You could use the nifty rle function to compute the vector of positions where it crosses over and directions. rle computes the lengths and values of the runs of a vector where it's identical, and we've passed it the binary vector of whether your values are non-negative.

pos <- head(cumsum(rle(flux >= 0)$lengths), -1)
pos
# [1] 2 3 4

All the remains is the interpolation and getting the directions:

(day[pos] + day[pos+1]) / 2
# [1] 2.5 4.0 7.5
c("positive", "negative")[head(rle(flux >= 0)$values + 1, -1)]
# [1] "positive" "negative" "positive"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top