<jupyter_start><jupyter_text>2 - Analiza el dataset caudal_extra.csv. ¿Qué puedes decir de los datos, distribuciones, missing, u otros? ¿Hay algo que te llame la atención? ¿Por qué hay tantos valores missing? Pensar en la manera en que se elaboró el dataset, descrito más arriba. (Entregable: texto/imágenes)<jupyter_code>df = pd.read_csv('caudal_extra.csv')
df = df.drop('Unnamed: 0', axis=1)
df
df.shape
df.isna().sum()
df[df['codigo_estacion'] == 4540001]['temp_max_promedio'].isna().value_counts()
df['caudal'].describe()
sns.distplot(df['caudal'].dropna())
plt.axvline(np.mean(df['caudal']), color='tomato')
sns.distplot(df['precip_promedio'].dropna())
plt.axvline(np.mean(df['precip_promedio']), color='tomato')
sns.distplot(df['temp_max_promedio'].dropna())
plt.axvline(np.mean(df['temp_max_promedio']), color='tomato')
sns.distplot(df['altura'].dropna())
plt.axvline(np.mean(df['altura']), color='tomato')<jupyter_output><empty_output><jupyter_text>RESPUESTA:  Existen datos perdidos en precip_promedio y especialmente en temp_max_promedio donde en este último poco más del 10 % de la muestras presenta datos perdidos. Según el como se elaboró el dataset, se indica en el enunciado que existen cuenca sin estaciones de tempertura o precipitación, por lo tanto es esperable que encontrar datos perdidos en estas variables. En cuanto a la distribución, caudal y precip_promedio se concentran viendo los histogramas muy fuerte en cantidades bajas, a diferencia de temp_max_promedio que se concentra prinicpalmente entre los 10 y 30 grados, siendo la media poco menos que 20 grados, entonces su distribución es muy similar a una normal. Algo que me llama la atención es que la base es que existe información histórica desde hace más de 50 años. Además me llama la atención lo completa que es la información en cuanto a información de las características de la cuenca.  3 - Plots de precipitación, temperatura y caudal  a. Escribir una función que tome como input una estación y haga plot de los datos para una columna. Debiese tener estos argumentos: def time_plot_una_estacion(codigo_estacion, columna, fecha_min, fecha_max):<jupyter_code>df.info()
df['fecha'] = pd.to_datetime(df['fecha'], format = '%Y/%m/%d')
df.info()
#plt.scatter(x=df[df['codigo_estacion'] == 7322001]['fecha2'], y=df[df['codigo_estacion'] == 7322001]['caudal'])
def time_plot_una_estacion(columna, fecha_min = '2000-12-01', fecha_max = '2003-12-01', codigo_estacion = 7322001):
    
    tmp = df[(df['fecha'] > fecha_min) & (df['fecha'] <= fecha_max)]
    
    sns.lineplot(x=tmp[tmp['codigo_estacion'] == codigo_estacion]['fecha'], 
                 y=tmp[tmp['codigo_estacion'] == codigo_estacion][columna], label = columna)
    plt.xticks(rotation=45, ha='right')
time_plot_una_estacion('caudal', '1975-01-01', '1985-01-01' )
def time_plot_estaciones_varias_columnas(columnas, fecha_min = '2000-01-01', fecha_max = '2000-07-01', codigo_estacion = 7322001):
          
    tmp = df[(df['fecha'] > fecha_min) & (df['fecha'] <= fecha_max)]
    
     
    for index, value in enumerate(columnas):
        
        tmp[columnas[index]] = ( tmp[columnas[index]]- tmp[columnas[index]].mean() )/ np.std(tmp[columnas[index]])
        
        sns.lineplot(x=tmp[tmp['codigo_estacion'] == codigo_estacion]['fecha'], 
                     y=tmp[tmp['codigo_estacion'] == codigo_estacion][columnas[index]], label = columnas[index])
        
        plt.xticks(rotation=45, ha='right')           
        plt.style.use('seaborn')
        plt.rcParams['figure.figsize']= (16, 10)         
                   
                   
aux = ['caudal', 'precip_promedio', 'temp_max_promedio' ]
time_plot_estaciones_varias_columnas(aux)<jupyter_output><empty_output><jupyter_text>4. Crea tres variables llamadas         ● caudal_extremo         ● temp_extremo         ● precip_extremo Dichas variables toman valor 1 un día si el caudal/temperatura/precipitación (según sea el caso)observado ese día es extremo. Esto significa que es mayor de lo "esperado". Para capturar esta idea,el valor de caudal, por ejemplo, toma valor 1 si está sobre el percentil 95 de ese caudal para esaestación del año (Verano, Primavera, Otoño, Invierno). Toma valor 0 cuando está bajo ese percentil.En otras palabras, para cada estación de medición y para cada estación del año, debes considerar ladistribución histórica de caudal/temperatura/precipitación para elegir ese percentil 95.Esta medida toma en cuenta la estacionalidad, pues, por ejemplo, una temperatura de 25 grados eninvierno puede ser extrema, pero en verano es normal. También toma en cuenta que cada cuenca (oestación) es diferente. Lo que es extremo para una cuenca no lo es para la otra.¿Les parece razonable esta medida para capturar algo “extremo”? ¿Usarían otra? ¿Cuál? ( Solamentedescríbanla, no la codifiquen! Vamos a usar la definición de Spike para esta desafío)<jupyter_code>bins = [0, 91, 183, 275, 366]
labels=['Verano', 'Otoño', 'Invierno', 'Primavera']
doy = df['fecha'].dt.dayofyear
df['estacion_año'] = pd.cut(doy + 11 - 366*(doy > 355), bins=bins, labels=labels)
df
df.groupby('estacion_año')['caudal'].quantile(0.95)
caudal_verano= df.groupby('estacion_año')['caudal'].quantile(0.95)[0]
caudal_otoño= df.groupby('estacion_año')['caudal'].quantile(0.95)[1]
caudal_invierno= df.groupby('estacion_año')['caudal'].quantile(0.95)[2]
caudal_primavera= df.groupby('estacion_año')['caudal'].quantile(0.95)[3]


df['caudal_extremo_verano'] = df[df['estacion_año'] == 'Verano']['caudal'].gt(caudal_verano).astype(int)
df['caudal_extremo_otoño'] = df[df['estacion_año'] == 'Otoño']['caudal'].gt(caudal_otoño).astype(int)
df['caudal_extremo_invierno'] = df[df['estacion_año'] == 'Invierno']['caudal'].gt(caudal_invierno).astype(int)
df['caudal_extremo_primavera'] = df[df['estacion_año'] == 'Primavera']['caudal'].gt(caudal_primavera).astype(int)
df['caudal_extremo_verano'] = df['caudal_extremo_verano'].fillna(0)
df['caudal_extremo_otoño'] = df['caudal_extremo_otoño'].fillna(0)
df['caudal_extremo_invierno'] = df['caudal_extremo_invierno'].fillna(0)
df['caudal_extremo_primavera'] = df['caudal_extremo_primavera'].fillna(0)
df['caudal_extremo_verano'].value_counts()
df['caudal_extremo'] = df['caudal_extremo_verano'] + df['caudal_extremo_otoño'] + df['caudal_extremo_invierno'] + df['caudal_extremo_primavera']
df['caudal_extremo'].value_counts()
df.groupby('estacion_año')['temp_max_promedio'].quantile(0.95)
temp_verano= df.groupby('estacion_año')['temp_max_promedio'].quantile(0.95)[0]
temp_otoño= df.groupby('estacion_año')['temp_max_promedio'].quantile(0.95)[1]
temp_invierno= df.groupby('estacion_año')['temp_max_promedio'].quantile(0.95)[2]
temp_primavera= df.groupby('estacion_año')['temp_max_promedio'].quantile(0.95)[3]
df['temp_extremo_verano'] = df[df['estacion_año'] == 'Verano']['temp_max_promedio'].gt(temp_verano).astype(int)
df['temp_extremo_otoño'] = df[df['estacion_año'] == 'Otoño']['temp_max_promedio'].gt(temp_otoño).astype(int)
df['temp_extremo_invierno'] = df[df['estacion_año'] == 'Invierno']['temp_max_promedio'].gt(temp_invierno).astype(int)
df['temp_extremo_primavera'] = df[df['estacion_año'] == 'Primavera']['temp_max_promedio'].gt(temp_primavera).astype(int)
df['temp_extremo_verano'] = df['temp_extremo_verano'].fillna(0)
df['temp_extremo_otoño'] = df['temp_extremo_otoño'].fillna(0)
df['temp_extremo_invierno'] = df['temp_extremo_invierno'].fillna(0)
df['temp_extremo_primavera'] = df['temp_extremo_primavera'].fillna(0)
df['temp_extremo'] = df['temp_extremo_verano'] + df['temp_extremo_otoño'] + df['temp_extremo_invierno'] + df['temp_extremo_primavera']
df['temp_extremo_verano'].value_counts()
df['temp_extremo'].value_counts()
df.groupby('estacion_año')['precip_promedio'].quantile(0.95)
prec_verano= df.groupby('estacion_año')['precip_promedio'].quantile(0.95)[0]
prec_otoño= df.groupby('estacion_año')['precip_promedio'].quantile(0.95)[1]
prec_invierno= df.groupby('estacion_año')['precip_promedio'].quantile(0.95)[2]
prec_primavera= df.groupby('estacion_año')['precip_promedio'].quantile(0.95)[3]
df['prec_extremo_verano'] = df[df['estacion_año'] == 'Verano']['precip_promedio'].gt(prec_verano).astype(int)
df['prec_extremo_otoño'] = df[df['estacion_año'] == 'Otoño']['precip_promedio'].gt(prec_otoño).astype(int)
df['prec_extremo_invierno'] = df[df['estacion_año'] == 'Invierno']['precip_promedio'].gt(prec_invierno).astype(int)
df['prec_extremo_primavera'] = df[df['estacion_año'] == 'Primavera']['precip_promedio'].gt(prec_primavera).astype(int)
df['prec_extremo_verano'] = df['prec_extremo_verano'].fillna(0)
df['prec_extremo_otoño'] = df['prec_extremo_otoño'].fillna(0)
df['prec_extremo_invierno'] = df['prec_extremo_invierno'].fillna(0)
df['prec_extremo_primavera'] = df['prec_extremo_primavera'].fillna(0)
df['prec_extremo'] = df['prec_extremo_verano'] + df['prec_extremo_otoño'] + df['prec_extremo_invierno'] + df['prec_extremo_primavera']
df['prec_extremo_verano'].value_counts()
df['prec_extremo'].value_counts()
df = df.drop('caudal_extremo_verano', axis=1)
df = df.drop('caudal_extremo_otoño', axis=1)
df = df.drop('caudal_extremo_invierno', axis=1)
df = df.drop('caudal_extremo_primavera', axis=1)

df = df.drop('temp_extremo_verano', axis=1)
df = df.drop('temp_extremo_otoño', axis=1)
df = df.drop('temp_extremo_invierno', axis=1)
df = df.drop('temp_extremo_primavera', axis=1)

df = df.drop('prec_extremo_verano', axis=1)
df = df.drop('prec_extremo_otoño', axis=1)
df = df.drop('prec_extremo_invierno', axis=1)
df = df.drop('prec_extremo_primavera', axis=1)
df<jupyter_output><empty_output><jupyter_text>Pregunta 4 -- ¿Les parece razonable esta medida para capturar algo “extremo”? ¿Usarían otra? ¿Cuál? ( Solamente descríbanla, no la codifiquen! Vamos a usar la definición de Spike para esta desafío)RESPUESTA: Intuitivamente sí me parece razonable, ya que la estacionalidad al presentar diferentes rangos de temperaturas es interesante revisar en cada período como se ha comportado, lo mismo en las precipitaciones que la estacionalidad también es considerable en este caso. En el caso del caudal, ahí intuitivamente pensaría que en períodos de mayor precipitación por ejemplo debiera haber mayor caudal, entonces es interesante ver el comportamiento por estación sin embargo creo que hay que tener bastante cuidado en la interpretación de los resultados.Esto debido a que es probable que existan en invierno fechas con caudales o precipitaciones que son mayores que en verano, pero no estén catalogadas como eventos extremos, y en verano sí.Entonces dependiendo de que es lo que nos interesa concluir puede necesario por ejemplo, el hacer un cálculo de valores extremos sin considerar la estación, ya que sí lo que me interesa es ver el caudal año a año y su evolución comparativamente en el global, al hacerlo por estación no entregaría la información que realmente necesito ver.En este caso considerando las preguntas que aparecen en la introducción, el criterio sugerido me parece una buena opción, aunque también lo evaluaría sin considerar la estacionalidad.  1. ¿Ha aumentado la frecuencia de olas de calor en Chile? Para esto se deben analizar las estaciones de temperatura   2. ¿Existe una relación entre olas de calor y eventos extremos de caudal?  3. De existir una relación entre olas de calor y eventos extremos de caudal, ¿se puede explicar este evento extremo por las características de la cuenca en donde ocurre el peakflow?  5. Analicen la variable caudal_extremo. Los comportamientos en diferentes cuencas son muy diferentes?<jupyter_code>sns.distplot(df['caudal_extremo'])
df[df['codigo_cuenca'] == 73]['caudal_extremo'].value_counts('%')
df[df['codigo_cuenca'] == 83]['caudal_extremo'].value_counts('%')
df[df['codigo_cuenca'] == 21]['caudal_extremo'].value_counts('%')
df[df['codigo_cuenca'] == 103]['caudal_extremo'].value_counts('%')
sns.boxplot(x=df['caudal_extremo'], y=df['codigo_cuenca'])<jupyter_output><empty_output><jupyter_text>Pregunta 5 --Analicen la variable caudal_extremo. Los comportamientos en diferentes cuencas son muy diferentes?RESPUESTA: Sí, se aprecia un comportamiento distinto en las cuencas. De hecho cuencas bajo el código 42-43 no tienen ningún caso extremo según se ve en el gráfico por ejemplo.  6. Hagan un plot del porcentaje de eventos extremos a través del tiempo (caudal_extremo, temp_extremo, precip_extremo).  Se han vuelto más o menos comunes?<jupyter_code>df.groupby('fecha')['caudal_extremo'].value_counts('%')
sns.lineplot(x=tmp[tmp['codigo_estacion'] == codigo_estacion]['fecha'], 
                     y=tmp[tmp['codigo_estacion'] == codigo_estacion][columnas[index]], label = columnas[index])
grouped = df.groupby('fecha')['caudal_extremo'].mean()
print(grouped)
#grouped.plot(ylim=(0,.5))
plt.plot(grouped)
grouped = df.groupby('fecha')['prec_extremo'].mean()
print(grouped)
#grouped.plot(ylim=(0,1))
plt.plot(grouped)
grouped = df.groupby('fecha')['temp_extremo'].mean()
print(grouped)
grouped.plot(ylim=(0,1))<jupyter_output>fecha
1960-01-02 00:00:00+00:00    0.000000
1960-01-03 00:00:00+00:00    0.000000
1960-01-04 00:00:00+00:00    0.000000
1960-01-05 00:00:00+00:00    0.000000
1960-01-06 00:00:00+00:00    0.000000
                               ...   
2018-03-05 00:00:00+00:00    0.034483
2018-03-06 00:00:00+00:00    0.137931
2018-03-07 00:00:00+00:00    0.000000
2018-03-08 00:00:00+00:00    0.000000
2018-03-09 00:00:00+00:00    0.034483
Name: temp_extremo, Length: 21252, dtype: float64<jupyter_text>7. Predicción de caudal extremo. Entrena uno o varios modelos (usando el/los algoritmo(s) que prefieras) para estimar la probabilidad de un caudal extremo (la variable binaria caudal_extremo). Siéntete libre de generar variables adicionales y/o complementar con variables externas<jupyter_code>from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, LogisticRegression
X_train, X_test, y_train, y_test = train_test_split(df.loc[:,['prec_extremo', 'temp_extremo']], df['caudal_extremo'], test_size=.33, random_state=11238)
modelo = LogisticRegression().fit(X_train, y_train)
yhat = modelo.predict(X_test)
yhat<jupyter_output><empty_output><jupyter_text>8. Análisis de resultado del modelo a. Qué performance tiene el modelo? Qué métricas usaste para medir esa performance? Cuáles son las variables más importantes? Qué opinión te merecen los resultados? b. Si quisiéramos capturar alrededor de un 70% de los eventos de caudales extremos. Cuál es la precisión de tu modelo con ese porcentaje de captura? Cuéntanos si te parece útil.<jupyter_code>from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
m1_confusion = confusion_matrix(y_test, yhat)
m1_confusion
print(classification_report(y_test, yhat))<jupyter_output>precision    recall  f1-score   support

         0.0       0.95      1.00      0.97    442715
         1.0       0.00      0.00      0.00     22975

    accuracy                           0.95    465690
   macro avg       0.48      0.50      0.49    465690
weighted avg       0.90      0.95      0.93    465690
{'fraction_non_alphanumeric': 0.12934696044597824, 'fraction_numerical': 0.03889036368462968, 'mean_word_length': 6.041588785046729, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '538780', 'license': 'MIT', 'n_tokens_mistral': 6041, 'n_tokens_neox': 5672, 'n_words': 1246, 'path': 'spikechallenge.ipynb', 'repo_name': 'nicotele/schallenge', 'size': '15068'}