25 votos

¿Cómo encontrar picos/valles locales en una serie de datos?

Este es mi experimento:

Estoy utilizando el findPeaks en la función quantmod paquete:

Quiero detectar picos "locales" dentro de una tolerancia 5, es decir, las primeras ubicaciones después de que la serie temporal se aleje de los picos locales en 5:

aa=100:1
bb=sin(aa/3)
cc=aa*bb
plot(cc, type="l")
p=findPeaks(cc, 5)
points(p, cc[p])
p

El resultado es

[1] 3 22 41

Me parece mal, ya que espero más "picos locales" que 3...

¿Alguna idea?

0voto

usando Numpy

ser = np.random.randint(-40, 40, 100) # 100 points
peak = np.where(np.diff(ser) < 0)[0]

o

double_difference = np.diff(np.sign(np.diff(ser)))
peak = np.where(double_difference == -2)[0]

utilizando Pandas

ser = pd.Series(np.random.randint(2, 5, 100))
peak_df = ser[(ser.shift(1) < ser) & (ser.shift(-1) < ser)]
peak = peak_df.index

0voto

No tengo suficiente reputación para comentar directamente sobre la respuesta de stas-g pero este es un comentario sobre un problema que encontré con el código de stas-g

Tengo vectores con datos incompletos

a = c(1.60676107, -1.84154137, -0.03814237, -3.01587711, 6.67004912, NA, NA, -0.94917515)
# Looking at the data find_peaks(a, m=3) should return 5
# and find_peaks(-a, m= 3) should return 4
find_peaks(a, m = 3)
# returns numeric(0) with the code as is
find_peaks(-a, m)
# returns an error

El error se debe a la evaluación de la condición todo

if(all(x[c(z : i, (i + 2) : w)] <= x[i + 1])) return(i + 1) else return(numeric(0))

En el primer caso el término a evaluar por all() devuelve FALSE antes de llegar a NA

y find_peaks(-a) falla porque all() devuelve NA y if(NA) falla.

Sin embargo añadiendo na.rm = T a all()

if(all(x[c(z : i, (i + 2) : w)] <= x[i + 1], na.rm = T)) return(i + 1) else return(numeric(0))

no resuelve el problema. find_peaks(-a,m=3) devuelve 4 pero find_peaks(a, m = 3) vuelve a devolver numeric(0) en lugar de 5

Al rellenar NA con el último valor válido antes de NA se añadirá un extremo local a los resultados y find_peaks(a, m= 3) devuelve 5 y 7

La función c++ de caseyk devuelve 4 y 5 como cabría esperar por observación visual

0voto

Nick Cook Puntos 1

Trabajo con registros largos de velocidades de viento enteras, incluidos los NA. Los valores enteros pueden tener mesetas planas que cuentan como picos y salientes que no cuentan. Mi solución sólo tarda 4,3 segundos en procesar un vector de 11,5 millones de elementos en mi PC:

indx.localpeaks<-function(x)  
{dw1<-sign(diff(x)) # -1=down, 0=flat, 1=up 
 names(dw1)<-c(1:length(dw1)) # tag names with original index
 i<-which(dw1==0)  # are there flats?   
 if (length(i)>0) dw1<-dw1[-i]  # close up flats 
 dw2<-diff(dw1) # second diff, peaks are -2
 indx<-as.numeric(names(which(dw2== -2))) # original index of peaks
 return(indx)
}

Así que

i<-indx.localpeaks(x)

indexa los picos agudos y el extremo posterior de cualquier meseta, pero los extremos frontales pueden obtenerse invirtiendo el vector x y el índice resultante

j<-length(x)+1-rev(indx.localpeaks(rev(x)))

Para encontrar valles, negar el vector x

k<-indx.localpeaks(-x)

En el ejemplo siguiente, los extremos traseros de las mesetas se muestran con círculos rojos y los extremos delanteros con círculos azules. Local peaks in integer wind speeds

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X