Advertisement
Guest User

Untitled

a guest
Oct 14th, 2019
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.50 KB | None | 0 0
  1. def change_detection(arr):
  2.     """
  3.    Funcion para detectar cambios en la serie temporal de NDVI, trabaja de forma hibrida con codigo R y Python
  4.    Requiere de los paquetes: numpy, pandas, rpy2 y la libreria strucchange (R)
  5.    Esta funcion fue programada por Miguel Moncada en octubre de 2019.
  6.    """
  7.  
  8.  
  9.     # Transformamos el input array a serie para trabajar con pandas
  10.    
  11.     series = pd.Series(arr)
  12.     window, scale = 46, 1.96
  13.    
  14.     # Computamos la media movil para el tamaño de ventana deseado y el n de desv. tipicas del intervalo de confianza
  15.    
  16.     rolling_mean = series.rolling(window=window).mean()
  17.    
  18.     # Calculamos el limite inferior del intervalo de confianza
  19.    
  20.     mae = mean_absolute_error(series[window:], rolling_mean[window:])
  21.     deviation = np.std(series[window:] - rolling_mean[window:])
  22.     lower_bond = rolling_mean - (mae + scale * deviation)
  23.    
  24.     # Creamos un array llamado 'lista' con la etiqueta del eje cuyo valor en 'y' es inferior al limite inferior
  25.    
  26.     lista = banda[np.less(series,lower_bond)]
  27.    
  28.    
  29.     # Incorporamos el codigo escrito en R a nuestro programa
  30.     # Esta funcion nos permite encontrar los puntos de cambio estructural en la serie de tiempo
  31.    
  32.     # Primero definimos la variable equivalente en R a nuestro array en Python
  33.     ro.globalenv["arr_r"] = arr
  34.    
  35.     # Creamos la funcion en R como string y la convertimos a objeto en R y despues en Python
  36.     struc = """
  37.    strchange <- function(){
  38.        strucchange::breakpoints(arr_r~1)[1]
  39.    }
  40.    """
  41.    
  42.     ro.r(struc)
  43.     strc_py = ro.globalenv['strchange']
  44.    
  45.     vector = np.array(strc_py()[0]).astype(int)
  46.    
  47.     # Creamos nuestros arrays vacios 'change' (donde incorporaremos anomalias - resultado final) y warn (incertidumbres)
  48.    
  49.     change = []
  50.     warn = []
  51.    
  52.     # Filtramos las anomalías que no nos interesan comprobando si el cambio se ha mantenido en los valores adyacentes
  53.     # Al comparar con los 3 siguientes valores, si nos encontramos con una anomalia al final de la serie tendremos warn
  54.    
  55.     for element in lista:
  56.        
  57.         if element >= 824:
  58.             warn.append(999)
  59.            
  60.         else:
  61.             a = arr[element-1]
  62.             b = arr[element]
  63.             c = arr[element+1]
  64.             d = arr[element+2]
  65.            
  66.             if isclose(a,b,rel_tol=0.25) & isclose(a,c,rel_tol=0.3) & isclose(b,c,rel_tol=0.25)\
  67.             & isclose(c,d,rel_tol=0.25):
  68.                     change.append(element)
  69.  
  70.     change = np.array(change)
  71.    
  72.     # Comprobamos que haya más de un valor anómalo consecutivo en nuestro array y eliminamos los casos puntuales
  73.    
  74.     for num in range(0,len(change)-2):
  75.         #if change[num] != 999:
  76.         if isclose(change[num],change[num+1], abs_tol=5) == False:
  77.             change = np.delete(change,num)
  78.            
  79.     # Comprobamos que los valores anómalos se encuentran en el rango de los breakpoints (cambios estructurales)
  80.    
  81.     change = np.array([i for i in change if np.isclose(vector, i, 5).any()])
  82.  
  83.     # Redondeamos para obtener el año del cambio en cuestion
  84.    
  85.     change = 2000 + np.floor(change/46)
  86.        
  87.     # Comprobamos que el array no esta vacio para evitar errores
  88.    
  89.     if change.size == 0:
  90.         change = np.append(change,0)
  91.    
  92.     # Obtenemos los valores unicos de nuestro array y devolvemos como salida el primero de estos
  93.        
  94.     change = np.unique(np.array(change)).astype(int)
  95.    
  96.    
  97.     return  change[0]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement