Group Abstract Group Abstract

Message Boards Message Boards

1
|
15.3K Views
|
9 Replies
|
8 Total Likes
View groups...
Share
Share this post:

Finding peaks and valleys in data

This will probably be trivial to some here, but I am trying to figure a function to find the peaks and valleys in a data sequence. For instance, given the following sequence: a = 10 5 3 6 9 15 13 12 9 15 18 20 19 18 ...

A peak is defined as (a[n] > a[n - 1] and a[n] > a[n + 1])

A valley is defined as (a[n] < a[n - 1] and a[n] < a[n + 1])

The peaks are 15 and 20 at indices 5 and 11 (index base 0)

The valleys are 3 and 9 at indices 2 and 8

I would like the result of the function to be of the form: 0 0 3 0 0 15 0 0 9 0 0 20 0 0 ...

or of the form {3 2} {15 5} {9 8} {20 11} ... {peak index} {valley index} ....

Basically, an alternating list of peaks and valleys or of valleys and peaks depending on whether we start with a peak or a valley. Those values that are neither peaks nor valleys are set to 0 in the result.

Or a list of pairs of the form {peak index} or {valley index}

POSTED BY: Henrick Jeanty
9 Replies

Check out functions FindPeaks and PeakDetect.

testList = {10, 5, 3, 6, 9, 15, 13, 12, 9, 15, 18, 20, 19, 18};
peaks = FindPeaks[testList];
valleys = {1, -1} # & /@ FindPeaks[-testList];
ListLinePlot[testList, Epilog -> {Red, PointSize[0.03], Point[peaks], Point[valleys]}]

enter image description here

POSTED BY: Vitaliy Kaurov

First a very quick comment: indices are referenced to 1 rather than 0 in Mathematica.

That said, here is an approach to finding the indices (positions in the list of data) where the peaks or valleys are located

In[1]:= testList = {10, 5, 3, 6, 9, 15, 13, 12, 9, 15, 18, 20, 19, 18};

In[2]:= peakTrippleQ[{x_, y_, z_}] := TrueQ[x < y > z]

In[3]:= peakPositions[list_List] := 
 Flatten[Position[peakTrippleQ /@ Partition[list, 3, 1], True] + 1]

In[4]:= valleyTrippleQ[{x_, y_, z_}] := TrueQ[x > y < z]

In[5]:= valleyPositions[list_List] := 
 Flatten[Position[valleyTrippleQ /@ Partition[list, 3, 1], True] + 1]

In[6]:= peakPositions[testList]

Out[6]= {6, 12}

In[7]:= valleyPositions[testList]

Out[7]= {3, 9}
POSTED BY: David Reiss

I think that Paul Wellin's recent book "Programming with Mathematica®: An Introduction" is quite good. Paul was the head of training at Wolfram Research for many years. The book is for Mathematica 9: it came out a year before version 10 came out, so the new things from version 10 are (obviously!) not discussed.

http://www.amazon.com/Programming-Mathematica-Introduction-Paul-Wellin/dp/1107009464

Nancy Blachman's book is quite good too but it is 13 years old and Mathematica had grown very considerably since then.

POSTED BY: David Reiss
POSTED BY: Henrick Jeanty
POSTED BY: Henrick Jeanty

Dear Henrick,

David's advice is what most people including me do - search documentation for keywords. You can even search them for functional syntax such as /@ if you unsure about it.

All discussions on this forum are public and everyone can read them. People participating on discussions get an email when the discussion gets any update. So do not worry about CC.

Welcome to Wolfram Community!

~ Vitaliy

POSTED BY: Vitaliy Kaurov

Hi Henrick,

Dont worry. I got CC'd on both of your replies!

By the way, I would have given you the answer that Vitaliy gave you but I forgot about FindPeaks as it is a new function in version 10.

The Documentation Center for Mathematica is actually quite helpful. If you type "find peak" into its search bar, the second and third result that it returns are PeakDetect and FindPeaks. So searching in the documentation is one thing to often try first if you are wondering if Mathematica has a built in functionality that addresses a problem you are working on.

Best regards, David

POSTED BY: David Reiss
POSTED BY: Henrick Jeanty

Thank you very much for your answer David,
I would have to analyze your answer to understand what each part is doing. However, I must let you know that I received another answer by Vitaliy Kaurov, and it was exactly what I wanted and, I must say, simpler. Here it is: testList = {10, 5, 3, 6, 9, 15, 13, 12, 9, 15, 18, 20, 19, 18}; peaks = FindPeaks[testList]; valleys = {1, -1} # & /@ FindPeaks[-testList]; ListLinePlot[testList, Epilog -> {Red, PointSize[0.03], Point[peaks], Point[valleys]}]

The answer is also in the format I need which is the index of that peak and the peak value. But thank you very much nonetheless. Regards, Henrick

POSTED BY: Henrick Jeanty
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard