Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- def change_detection(arr):
- """
- Funcion para detectar cambios en la serie temporal de NDVI, trabaja de forma hibrida con codigo R y Python
- Requiere de los paquetes: numpy, pandas, rpy2 y la libreria strucchange (R)
- Esta funcion fue programada por Miguel Moncada en octubre de 2019.
- """
- # Transformamos el input array a serie para trabajar con pandas
- series = pd.Series(arr)
- window, scale = 46, 1.96
- # Computamos la media movil para el tamaño de ventana deseado y el n de desv. tipicas del intervalo de confianza
- rolling_mean = series.rolling(window=window).mean()
- # Calculamos el limite inferior del intervalo de confianza
- mae = mean_absolute_error(series[window:], rolling_mean[window:])
- deviation = np.std(series[window:] - rolling_mean[window:])
- lower_bond = rolling_mean - (mae + scale * deviation)
- # Creamos un array llamado 'lista' con la etiqueta del eje cuyo valor en 'y' es inferior al limite inferior
- lista = banda[np.less(series,lower_bond)]
- # Incorporamos el codigo escrito en R a nuestro programa
- # Esta funcion nos permite encontrar los puntos de cambio estructural en la serie de tiempo
- # Primero definimos la variable equivalente en R a nuestro array en Python
- ro.globalenv["arr_r"] = arr
- # Creamos la funcion en R como string y la convertimos a objeto en R y despues en Python
- struc = """
- strchange <- function(){
- strucchange::breakpoints(arr_r~1)[1]
- }
- """
- ro.r(struc)
- strc_py = ro.globalenv['strchange']
- vector = np.array(strc_py()[0]).astype(int)
- # Creamos nuestros arrays vacios 'change' (donde incorporaremos anomalias - resultado final) y warn (incertidumbres)
- change = []
- warn = []
- # Filtramos las anomalías que no nos interesan comprobando si el cambio se ha mantenido en los valores adyacentes
- # Al comparar con los 3 siguientes valores, si nos encontramos con una anomalia al final de la serie tendremos warn
- for element in lista:
- if element >= 824:
- warn.append(999)
- else:
- a = arr[element-1]
- b = arr[element]
- c = arr[element+1]
- d = arr[element+2]
- if isclose(a,b,rel_tol=0.25) & isclose(a,c,rel_tol=0.3) & isclose(b,c,rel_tol=0.25)\
- & isclose(c,d,rel_tol=0.25):
- change.append(element)
- change = np.array(change)
- # Comprobamos que haya más de un valor anómalo consecutivo en nuestro array y eliminamos los casos puntuales
- for num in range(0,len(change)-2):
- #if change[num] != 999:
- if isclose(change[num],change[num+1], abs_tol=5) == False:
- change = np.delete(change,num)
- # Comprobamos que los valores anómalos se encuentran en el rango de los breakpoints (cambios estructurales)
- change = np.array([i for i in change if np.isclose(vector, i, 5).any()])
- # Redondeamos para obtener el año del cambio en cuestion
- change = 2000 + np.floor(change/46)
- # Comprobamos que el array no esta vacio para evitar errores
- if change.size == 0:
- change = np.append(change,0)
- # Obtenemos los valores unicos de nuestro array y devolvemos como salida el primero de estos
- change = np.unique(np.array(change)).astype(int)
- return change[0]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement