Skip to content

peak finding

8 messages · Research Scholar, Bill Venables, Christos Hatzis +3 more

#
It's hard to see how positions 4 and 14 correspond to 'peaks', they look
like troughs to me.  So perhaps this is what you mean:
[1]  4 14 

as a function:

somefunction <- function(x) which(x == min(x))


Bill Venables
CSIRO Laboratories
PO Box 120, Cleveland, 4163
AUSTRALIA
Office Phone (email preferred): +61 7 3826 7251
Fax (if absolutely necessary):  +61 7 3826 7304
Mobile:                         +61 4 8819 4402
Home Phone:                     +61 7 3286 7700
mailto:Bill.Venables at csiro.au
http://www.cmis.csiro.au/bill.venables/ 

-----Original Message-----
From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org]
On Behalf Of Research Scholar
Sent: Tuesday, 25 March 2008 12:54 PM
To: r-help at r-project.org
Subject: [R] peak finding

Hi all
 Is there a function that can find the start and end position of peaks
in a
set of numbers.
eg.
x <- c(14,15,12,11,12,13,14,15,16,15,14,13,12,11,14,12)
y <- somefunction(x)

y
4 14


Thanks
John


______________________________________________
R-help at r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide
http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.
#
Then the answer is pretty simple: 'no'.

The idea probably needs a lot more refining to make it workable, too.
Why do you discard he peak at 2, with the shape starting at 1 and
finishing at 4, for example?

In thinking about this it might be useful for you to look at signs of
successive differences:
[1]  1  1 -1 -1  1  1  1  1  1 -1 -1 -1 -1 -1  1 -1

That's perhaps a starting point.  You seem to want to know (roughly)
"where do the runs of '1's start and the following run of '-1's end?"
The function rle(), for run length encoding, might be useful in this
regard, too.

Bill Venables. 


-----Original Message-----
From: Research Scholar [mailto:thesis1977 at gmail.com] 
Sent: Tuesday, 25 March 2008 1:24 PM
To: Venables, Bill (CMIS, Cleveland)
Cc: r-help at r-project.org
Subject: Re: [R] peak finding

Hi
 Thanks for replying. I meant x[4] is the start of a peak shape and
x[14] is the end of that peak and x[9] is the maxima of the peak. 
Thanks,
John
On Mon, Mar 24, 2008 at 11:09 PM, <Bill.Venables at csiro.au> wrote:
It's hard to see how positions 4 and 14 correspond to 'peaks',
they look
	like troughs to me.  So perhaps this is what you mean:
	

	> x <- c(14,15,12,11,12,13,14,15,16,15,14,13,12,11,14,12)
	
	
	> y <- which(x == min(x))
	> y
	[1]  4 14
	
	as a function:
	
	somefunction <- function(x) which(x == min(x))
	
	
	Bill Venables
	CSIRO Laboratories
	PO Box 120, Cleveland, 4163
	AUSTRALIA
	Office Phone (email preferred): +61 7 3826 7251
	Fax (if absolutely necessary):  +61 7 3826 7304
	Mobile:                         +61 4 8819 4402
	Home Phone:                     +61 7 3286 7700
	mailto:Bill.Venables at csiro.au
	http://www.cmis.csiro.au/bill.venables/
	

	-----Original Message-----
	From: r-help-bounces at r-project.org
[mailto:r-help-bounces at r-project.org]
	On Behalf Of Research Scholar
	Sent: Tuesday, 25 March 2008 12:54 PM
	To: r-help at r-project.org
	Subject: [R] peak finding
	
	Hi all
	 Is there a function that can find the start and end position of
peaks
	in a
	set of numbers.
	eg.
	x <- c(14,15,12,11,12,13,14,15,16,15,14,13,12,11,14,12)
	y <- somefunction(x)
	
	y
	4 14
	
	
	Thanks
	John
	
	
	
	______________________________________________
	R-help at r-project.org mailing list
	https://stat.ethz.ch/mailman/listinfo/r-help
	PLEASE do read the posting guide
	http://www.R-project.org/posting-guide.html
	and provide commented, minimal, self-contained, reproducible
code.
#
John,

There is a peak finding algorithm attributed to Prof. Ripley in the R-help
archive.  It has a span parameter which might give you something close to
what you seem to be looking for.

http://finzi.psych.upenn.edu/R/Rhelp02a/archive/33097.html 

-Christos
#
Another approach that involves more infrastructure is to fit a smooth
line to your points, compute the first derivative, and look for change
in sign in the first derivative.

eg

x <- c(14,15,12,11,12,13,14,15,16,15,14,13,12,11,14,12)

smoothed.dx <- predict(smooth.spline(x), deriv=1)$y

which(c(smoothed.dx,NA) > 0 & c(NA, smoothed.dx) < 0)



My experience is that this approach sometimes requires some
fine-tuning, eg in fitting the smooth.

I hope that this helps

Andrew
On Mon, Mar 24, 2008 at 11:23:57PM -0400, Research Scholar wrote:

  
    
#
I am not sure how to implement this in R, but beam forming, used in
geophysics, sounds like an alternative.  We are currently looking at
this with the help of a matlab guru to look at the shift in the
dissolved oxygen peaks as you go down river.  This assumes that you
have an array of reading sepperated by space.  Schumway's book
mentions this.
On Tue, Mar 25, 2008 at 11:25 AM, Robert A LaBudde <ral at lcfltd.com> wrote:

  
    
#
At 10:48 PM 3/24/2008, Chistos wrote:
Finding peaks and valleys has several issues:

1. Impact of noise.
2. Mathematical smoothness of the underlying signal.
3. Boundary conditions at the beginning and end of the data series.
4. Bias from smoothing.

If the noise is not too bad, I'd try fitting a smoothing spline, and 
then use the null derivative points to punctuate the extrema.

If the noise is severe, you probably will need some domain knowledge, 
and will end up with perhaps locally weighted regression, followed by 
extrema search.

For cases where the noise is trivial, the following short function 
might be useful in picking off peaks (and symmetrically modified, valleys):

#findpeaks()
#Copyright 2007 by Robert A LaBudde, all rights reserved
#find peaks in (x,y) curve
findpeaks<- function(x, y) {
   nx<- length(x)
   ny<- length(y)
   if (nx != ny) {
     print ('>> findpeaks01: x and y must be same length!')
     stop
     }
   ipeak<- NULL
   xpeak<- NULL
   ypeak<- NULL
   yprv<- y[1]
   for (i in 1:ny) {
     ynext<- ifelse(i==ny,y[ny],y[i+1])
     if(yprv < y[i] & y[i] > ynext) { #found local peak
       ipeak<- c(ipeak,i)
       xpeak<- c(xpeak,x[i])
       ypeak<- c(ypeak,y[i])
       }
     yprv<- y[i]
     }
   return(data.frame(ipeak,x=xpeak,y=ypeak))
   }

Trivial though it may be, it actually works quite well for its 
intended purpose.

================================================================
Robert A. LaBudde, PhD, PAS, Dpl. ACAFS  e-mail: ral at lcfltd.com
Least Cost Formulations, Ltd.            URL: http://lcfltd.com/
824 Timberlake Drive                     Tel: 757-467-0954
Virginia Beach, VA 23464-3239            Fax: 757-467-2947

"Vere scire est per causas scire"