Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Peak Detection in Time Series

I'm currently working on a little project in which I want to compare two time-series. The similarity measure is really vague, they are considered to be similar if the two time series roughly have the same shape.

So I thought to myself "Well if they only need to have the same shape, I just compare the peaks of the two time-series, if the peaks are at the same position, then surely the time-series will be similar"

My problem now is to find a good algorithm for the peak detection. I used google, but I only came up with the paper Simple Algorithms for Peak Detection in Time-Series. The problem is, the algorithms described in this paper work well with really extreme and thin peaks, but in the most cases, my time-series have rather flat peaks so they will not be detected.

Does anybody know where I could find or search for an algorithm which would detect the peaks shown in the following image?

time-series

like image 279
IdealOutage Avatar asked Sep 03 '12 14:09

IdealOutage


People also ask

How do you find the peak of a time series?

Find the peaks using a threshold. Find the distance between two consecutive peaks. Calculate the median between 2 peaks. Find the start and the end by comparing the current value to the median, i.e. if the current value is smaller than the median but the next one is bigger, a peak starts.

What is peak detection?

Definition: Peak detector circuits are used to determine the peak (maximum) value of an input signal. It stores the peak value of input voltages for infinite time duration until it comes to reset condition.


2 Answers

You seem to simply look for slope inversion (from positive to negative and vice versa). A rough java algo could be (not tested):

List<Point> points = ... //all the points in your curve
List<Point> extremes = new ArrayList<Point> ();
double previous = null;
double previousSlope = 0;

for (Point p : points) {
    if (previous == null) { previous = p; continue; }
    double slope = p.getValue() - previous.getValue();
    if (slope * previousSlope < 0) { //look for sign changes
        extremes.add(previous);
    }
    previousSlope = slope;
    previous = p;
}

Finally, a good way to measure similarity is correlation. In your case, I would look at % move correlation (in other words, you want your 2 series to go up or down at the same time) - that's typically what is done in finance where you calculate the correlation between 2 assets returns for example:

  • create 2 new series with the % move for each point of the 2 series
  • calculate the correlation between those 2 series

You can read more about returns correlations here for example. In summary, if your values are:

Series 1  Series 2
 100        50
 98         49
 100        52
 102        54

The "returns" series will be:

Series 1  Series 2
 -2.00%     -2.00%
 +2.04%     +6.12%
 +2.00%     +3.85%

And you calculate the correlation of those 2 returns series (in this example: 0.96) to get a measure of how much the 2 curves look alike. You might want to adjust the result for variance (i.e. if one shape has a much wider range than the other).

like image 157
assylias Avatar answered Sep 20 '22 13:09

assylias


You can use a very simple local extremes detector:

// those are your points:
double[] f = {1, 2, 3, 4, 5, 6, 5, 4, 7, 8, 9, 3, 1, 4, 6, 8, 9, 7, 4, 1};
List<Integer> ext = new ArrayList<Integer> ();
for (int i = 0; i<f.length-2; i++) {
  if ((f[i+1]-f[i])*(f[i+2]-f[i+1]) <= 0) { // changed sign?
    ext.add(i+1);
  }
}
// now you have the indices of the extremes in your list `ext`

This will work nice with smooth series. If you have a certain variation in your data, you should put it through a low pass filter first. A very simple implementation of a low pass filter would be the moving average (every point is replaced by the average of the nearest k values, with k being the window size).

like image 43
brimborium Avatar answered Sep 19 '22 13:09

brimborium