Commit c07c2fff authored by Poulard Christine's avatar Poulard Christine :snake:
Browse files

Update Atelier_MatPlotLib_2021_part1.py

parent b55977de
No related merge requests found
Showing with 710 additions and 897 deletions
+710 -897
......@@ -17,10 +17,11 @@ import matplotlib.pyplot as plt
# des éléments complémentaires (on verra leur utilité)
import matplotlib.gridspec as gridspec
import matplotlib.dates as mpldates # https://matplotlib.org/examples/api/date_demo.html
import matplotlib.dates as mdates # https://matplotlib.org/examples/api/date_demo.html
from matplotlib.dates import DateFormatter
import matplotlib.colors as mocolor
from matplotlib.patches import Rectangle
from matplotlib.lines import Line2D
from matplotlib.colors import ListedColormap
from matplotlib.collections import PatchCollection
......@@ -48,26 +49,36 @@ import pickle as pl
# CONSTANTES - convention : en majuscule
DICO_NOM_MOIS = {1: 'janv', 2: 'févr', 3: 'mars', 4: 'avr', 5: 'mai', 6: 'juin', 7: 'juil', 8: 'août',
9:'sept', 10:'oct', 11:'nov', 12:'déc'}
# les noms de fichiers de données
REP_DONNEES = "C:/WorkSpace/2021-Tuto-Python/Code/donnees" # remplacez par votre chemin
TD4_ENTPE_TPQ_original = "TD4-donneesTPQ.txt" # date au format "janv-00" : bon exercice pour "parser" en utilisant un dico
TD4_ENTPE_pv = "ChroniquesTPluieQ_pointvirgule.csv" # même données avec des dates au format JJ/MM/AAAA, séparateur = ;
TD4_ENTPE_tab = "ChroniquesTPQ_tabulations.txt" # même données avec des dates au format JJ/MM/AAAA, séparateur = blanc ou tabulation
DICO_COULEURS_MOIS = {1: "dimgrey", 2: "black", 3: "palegreen", 4: 'mediumspringgreen', 5: 'forestgreen', 6: 'gold', 7: 'orange',
8:'orangered', 9:'deepskyblue', 10:'royalblue', 11:'navy', 12:'silver'}
HYDRO_QJO = "B2220010_qj_hydro2_2019.txt"
HYDRO_Qt = "B2220010_qtvar.txt"
HYDROQJ = "Y2372010_qj.csv"
CHAMP_BIN = "chronique_bloc_38_57_test2.bin"
CHAMP_GRID = "Panthere_20160512_LimBvGC_zoom1_0_Champ journalier.grd"
trace_plt = True
trace_pd = True
# CLASSES (même si en fait l'ordre importe peu...)
# pas encore de classe ici
# FONCTIONS
def afficher_legende_code_couleur_mois(titre="Code couleur \n des mois"):
# on crée
plt.ion()
fig, ax = plt.subplots()
ax.axis('off')
handles = [Line2D([0], [0], marker='o', color="b", label=DICO_NOM_MOIS[mois],
markerfacecolor=DICO_COULEURS_MOIS[mois], markersize=15) for mois in range(1, 13)]
fig.legend(handles=handles, ncol=1, title=titre, fontsize=8, title_fontsize=10,
labelspacing=1.5)
# plt.show(block = False)
"""
if Path.is_file(Path(IKONKA)):
thismanager = plt.get_current_fig_manager()
thismanager.window.tk.call('wm', 'iconphoto', thismanager.window._w, Photoimage(file=IKONKA))
"""
fig.canvas.draw()
plt.ioff()
# GRAPHIQUE SIMPLE
# format Hydro2 "QJO"
......@@ -146,7 +157,7 @@ def lecteur_qj0_to_ts(nom_fichier, trace=True):
return qj_series
def donnees_TD_ETP_csv(nom_fichier, separateur=";"):
def donnees_TD_ETP_csv_panda_seul(nom_fichier, separateur=";"):
"""
Lecteur du fichier TD4 ChroniquesTPluieQ_pointvirgule
......@@ -159,15 +170,9 @@ def donnees_TD_ETP_csv(nom_fichier, separateur=";"):
"""
#note : # https: // stackoverflow.com / questions / 25416955 / plot - pandas - dates - in -matplotlib
# fonction imbriquée dans la première, pour la mise en forme des données
# format the coords message box
def un_chiffre_apres_la_virgule(x):
# return '%1.1f unités' % x
return f"{x:.1f} unités"
DF_TD4 = pd.read_csv(nom_fichier, sep=separateur, decimal=',')
#on affiche les 5 premières lignes
#on affiche les 5 premières lignes pour vérifier
DF_TD4.head(5)
nom_colonnes = DF_TD4.columns.tolist()
......@@ -176,15 +181,8 @@ def donnees_TD_ETP_csv(nom_fichier, separateur=";"):
# on affiche les 15 premières valeurs de la colonne n°0
print(DF_TD4[nom_colonnes[0]][:15])
# pour assigner un format date à la première colonne, on a plusieurs possibilités :
# une façon "besogneuse" en découpant et collant les morceaux, comme à la première étape
# jmas = [date_str.split('/') for date_str in DF_TD4[nom_colonnes[0]]] # jmas est une liste de listes de 3 items
# dates_dt = [[datetime(int(a), int(m), int(j))] for j, m, a in jmas] # for j, m, a in jmas : on unpacke la liste
# puisqu'il y a des séparateurs on peut aussi utiliser un lecteur de format du module datetime
# DF_TD4[nom_colonnes[0]].apply(lambda x: datetime.strptime(str(x), "%d/%m/%Y"))
# ou enfin une méthode élégante de pandas, qui "se débrouille pour lire une date si c'est une date"
# pour assigner un format date à la première colonne,
# on s'en remet à pandas, qui "se débrouille pour lire une date si c'est une date"
# date_au_format_pandas = pd.to_datetime(un_truc_nimporte_comment_qui_est_une_date)
# piège ; on ne sait jamais si c'est MMDD ou DDMM : l'argument dayfirst=True permet de cadrer le déchiffrage
......@@ -197,13 +195,10 @@ def donnees_TD_ETP_csv(nom_fichier, separateur=";"):
# une fois convaincus, on peut faire la conversion directement dans la colonne
DF_TD4[nom_colonnes[0]] = pd.to_datetime(DF_TD4[nom_colonnes[0]], dayfirst=True)
# sinon il y aurait une façon "besogneuse" :
# DF_TD4[nom_colonnes[0]].apply(lambda x: datetime.strptime(str(x), "%d/%m/%Y"))
# on déclare comme index la colonne, avec les dates ; elle prend donc un statut particulier
DF_TD4.set_index(nom_colonnes[0], inplace=True)
# on met à jour la liste des colonnes (on a supprimé une colonne "dates")
# on met à jour la liste des colonnes (on a supprimé une colonne "dates", qui est devenue l'index)
nom_colonnes = DF_TD4.columns.tolist()
print("Noms des colonnes après avoir défini l'index : ", nom_colonnes)
......@@ -212,15 +207,10 @@ def donnees_TD_ETP_csv(nom_fichier, separateur=";"):
DF_TD4.head(5)
fig, ax = plt.subplots() # on verra juste après cette syntaxe
DF_TD4.plot(ax=ax)
fig.suptitle("En utilisant les possibilités de pandas")
# idem, on laisse pandas se débrouiller complètement
DF_TD4.plot()
plt.suptitle("En utilisant les possibilités de pandas")
plt.legend()
# plt.gca().format_xdata = mpldates.DateFormatter('%Y/%m')
# plt.gca().format_ydata = un_chiffre_apres_la_virgule
# plt.gcf().autofmt_xdate() # sur figure
plt.show()
return DF_TD4
......@@ -242,8 +232,23 @@ def donnees_TD_ETP_2subplots(nom_fichier):
nom_colonnes = DF_TD4.columns.tolist()
print("Noms de colonnes lus dans le csv : ", nom_colonnes)
#première figure : PANDAS
# méthode plot de pandas
DF_TD4.plot()
plt.suptitle("En utilisant les possibilités de pandas")
plt.gcf().canvas.set_window_title("PTQ_avec_pandas")
plt.legend()
# plt.gca().format_xdata = mpldates.DateFormatter('%Y/%m')
# plt.gca().format_ydata = un_chiffre_apres_la_virgule
# plt.gcf().autofmt_xdate() # sur figure
plt.show()
plt.close()
# on découpe la figure en deux subplots
fig, (ax_pluie, ax_q) = plt.subplots(ncols=1, nrows=2, sharex=True)
fig.canvas.set_window_title("PTQ_2subplots")
fig.subplots_adjust(bottom=0.15)
fig.suptitle("Forçages en haut, réponse du bassin en bas")
......@@ -257,747 +262,780 @@ def donnees_TD_ETP_2subplots(nom_fichier):
etiquette_temperatures = nom_colonnes[0]
ax_t.set_ylabel(etiquette_temperatures)
ax_t.plot(liste_dates, DF_TD4[etiquette_temperatures].tolist(), marker='*', color='orange', ls=':',
label=etiquette_temperatures, zorder=50)
label=etiquette_temperatures)
etiquette_debit = nom_colonnes[2]
ax_q.set_ylabel(etiquette_debit, color='blue')
ax_q.plot(liste_dates, DF_TD4[etiquette_debit].tolist(), marker='>', color='blue', ls=':', label=etiquette_debit)
fig.legend(bbox_to_anchor=(1, 0), loc="lower right",
bbox_transform=fig.transFigure, ncol=3)
# plt.gca().format_xdata = mpldates.DateFormatter('%Y/%m')
# plt.gca().format_ydata = un_chiffre_apres_la_virgule
# plt.gcf().autofmt_xdate() # sur figure
#le module pickle
# nom_fichier_pickle = Path(nom_fichier).with_suffix('.pickle')
# pl.dump(fig, open(nom_fichier_pickle, 'wb'))
# print(nom_fichier_pickle)
bbox_transform=fig.transFigure, ncol=4)
plt.show()
return DF_TD4
def donnees_TD_ETP_2subplots_variante(DF_PTQ):
"""
# on prend en argument un DataFrame
et on fait un graphique avec d'autres solutions que plot et lines
"""
# couleurs par mois : prétexte pour manipuler dictionnaires et scatter
# équivalent "plus lisible" de : liste_couleurs = [ DICO_COULEURS_MOIS[date.month] for date in DF_PTQ.index]
liste_couleurs = []
for date in DF_PTQ.index:
liste_couleurs.append(DICO_COULEURS_MOIS[date.month])
def trace_avec_plt(liste_dates, valeurs, type_graphe="plot"):
temps = datetime.now() - debut
# plt.suptitle("trace_avec_plt - fig.suptitle")
if type_graphe == "plot":
plt.plot(liste_dates, valeurs)
plt.title("Avec pyplot, plot")
elif type_graphe == "stem":
plt.stem(liste_dates, valeurs)
plt.title("Avec pyplot, stem")
elif type_graphe == "hlines":
plt.hlines(y=valeurs, xmin=liste_dates, xmax=[date + timedelta(days=30) for date in liste_dates])
elif type_graphe == "vlines":
plt.vlines(x=liste_dates, ymin=0, ymax=valeurs)
# pour améliorer
plt.xticks(rotation=45)
plt.tight_layout(True)
# plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0)
# plt.tight_layout({'rect': [0, .15, 1, 0.9]}, w_pad=0.5, h_pad=1.0)
plt.subplots_adjust(bottom=0.2)
# fig.autofmt_xdate()
val_moy = max(valeurs) / 2
# tests stem et vline sur qq valeurs
# plt.stem([liste_dates[0],liste_dates[-1]], [val_moy, val_moy ])
# plt.vlines([liste_dates[5], liste_dates[-10]], [0, 0], [val_moy, val_moy], colors=["red", "green"])
plt.title("Avec pyplot, " + type_graphe)
plt.gcf().canvas.set_window_title("Avec_pyplot_" + type_graphe)
plt.show()
print("temps écoulé Pyplot avec plot:", temps)
# plt.clf()
return temps
nom_colonnes = DF_PTQ.columns.tolist()
# on découpe la figure en deux subplots
fig, (ax_pluie, ax_q) = plt.subplots(ncols=1, nrows=2, sharex=True)
fig.canvas.set_window_title("PTQ_2subplots")
fig.subplots_adjust(bottom=0.15)
fig.suptitle("Forçages en haut, réponse du bassin en bas")
def trace_au_choix(serie, type_graphe="plot"):
temps = datetime.now() - debut
etiquette_pluie = nom_colonnes[1]
ax_pluie.set_ylabel(etiquette_pluie, color='lightblue')
ax_pluie.step(x=DF_PTQ.index, y=DF_PTQ[etiquette_pluie].tolist(), color='lightblue', lw=2,
label=etiquette_pluie, where='post')
ax_pluie.fill_between(DF_PTQ.index, DF_PTQ[etiquette_pluie].tolist(), step="post", alpha=0.4)
ax_pluie.invert_yaxis()
if type_graphe == "plot":
ax_t = ax_pluie.twinx()
etiquette_temperatures = nom_colonnes[0]
ax_t.set_ylabel(etiquette_temperatures)
ax_t.step(DF_PTQ.index, DF_PTQ[etiquette_temperatures].tolist(), marker='None', color='orange', ls=':',
label=etiquette_temperatures + " (step)", where="post")
# todo : on a un peu forcé le "scatter" pour s'exercer
ax_t.scatter(DF_PTQ.index, DF_PTQ[etiquette_temperatures].tolist(), marker='*', ls=':',
label=etiquette_temperatures, c=liste_couleurs)
serie.plot()
etiquette_debit = nom_colonnes[2]
ax_q.set_ylabel(etiquette_debit, color='blue')
ax_q.step(DF_PTQ.index, DF_PTQ[etiquette_debit].tolist(), marker='None', color='blue', ls='-', label=etiquette_debit, where='post')
elif type_graphe == "hlines":
plt.hlines(y=serie, xmin=serie.index, xmax=[date + timedelta(days=30) for date in serie.index])
fig.legend(bbox_to_anchor=(1, 0), loc="lower right",
bbox_transform=fig.transFigure, ncol=4)
plt.title("Avec pyplot, hines")
#le module pickle
# nom_fichier_pickle = Path(nom_fichier).with_suffix('.pickle')
# pl.dump(fig, open(nom_fichier_pickle, 'wb'))
# print(nom_fichier_pickle)
plt.show()
# pas d'instruction return, mais par défaut la fonction retourne quand même... None
print("temps écoulé, fonction trace_au_choix :", temps)
# plt.clf()
return temps
def tracer_DF_lamedeau_moyennes_mobiles(series_or_df_lamedeau):
# format the coords message box
def un_chiffre_apres_la_virgule(x):
# return '%1.1f unités' % x
return f"{x:.1f} mm/5 min"
# DF_moymobile_1j et 30 jours définis pour le plot mais non nommés
if type(series_or_df_lamedeau) == pd.Series:
df_ler5min = series_or_df_lamedeau.to_frame()
else:
df_ler5min = series_or_df_lamedeau # deepcopy
df_ler5min.columns = ["Lame d'eau radar à 5 mm, en mm"]
df_ler5min.columns.name = 'Chroniques'
fig, (ax_moy, ax_ler) = plt.subplots(nrows=2, ncols=1, sharex=True)
fig.subplots_adjust(bottom=0.3)
def donnees_TD_ETP_2subplots_variante2(DF_PTQ):
"""
# on prend en argument un DataFrame
et on fait un graphique avec d'autres solutions que plot et lines
"""
# couleurs par mois : prétexte pour manipuler dictionnaires et scatter
# équivalent "plus lisible" de : liste_couleurs = [ DICO_COULEURS_MOIS[date.month] for date in DF_PTQ.index]
liste_couleurs = []
for date in DF_PTQ.index:
liste_couleurs.append(DICO_COULEURS_MOIS[date.month])
fig.suptitle("Lames d'eau radar et cumuls, en utilisant pandas")
couleur_5min = 'blue'
ax_ler.set_ylabel("Lame d'eau radar \n (mm en 5 mm)", color=couleur_5min)
# méthode plot de pandas appliquée à un dataframe
df_ler5min.plot(ax=ax_ler, color=couleur_5min)
nom_colonnes = DF_PTQ.columns.tolist()
# on découpe la figure en deux subplots
fig, (ax_pluie, ax_codemois, ax_q) = plt.subplots(ncols=1, nrows=3, sharex=True)
fig.canvas.set_window_title("PTQ_2subplots")
fig.subplots_adjust(bottom=0.15)
fig.suptitle("Forçages en haut, réponse du bassin en bas")
couleur_24h = 'red'
ax_moy.set_ylabel("Cumuls sur 24 h (mm)", color=couleur_24h)
df_24h = df_ler5min.rolling('1d').sum()
df_24h.columns = ["Cumuls mobiles sur 24h"]
df_24h.plot(ax=ax_moy, color=couleur_24h, label="ça sert à rien")
etiquette_pluie = nom_colonnes[1]
ax_pluie.set_ylabel(etiquette_pluie, color='lightblue')
ax_pluie.step(x=DF_PTQ.index, y=DF_PTQ[etiquette_pluie].tolist(), color='lightblue', lw=2,
label=etiquette_pluie, where='post')
ax_pluie.fill_between(DF_PTQ.index, DF_PTQ[etiquette_pluie].tolist(), step="post", alpha=0.4)
ax_pluie.invert_yaxis()
couleur_30j = 'orange'
ax_moy_30j = ax_moy.twinx()
ax_moy_30j.set_ylabel("Cumuls sur 30 jours", color=couleur_30j)
ax_t = ax_pluie.twinx()
etiquette_temperatures = nom_colonnes[0]
ax_t.set_ylabel(etiquette_temperatures)
ax_t.step(DF_PTQ.index, DF_PTQ[etiquette_temperatures].tolist(), marker='None', color='orange', ls=':',
label=etiquette_temperatures + " (step)", where="post")
# todo : on a un peu forcé le "scatter" pour s'exercer
ax_t.scatter(DF_PTQ.index, DF_PTQ[etiquette_temperatures].tolist(), marker='*', ls=':',
label=etiquette_temperatures, c=liste_couleurs)
df_30j = df_ler5min.rolling('30d').sum()
df_30j.columns = ["Cumuls mobiles sur 30 jours"]
df_30j.plot(ax=ax_moy_30j, color=couleur_30j)
etiquette_debit = nom_colonnes[2]
ax_q.set_ylabel(etiquette_debit, color='blue')
ax_q.step(DF_PTQ.index, DF_PTQ[etiquette_debit].tolist(), marker='None', color='blue', ls='-', label=etiquette_debit, where='post')
for ax in [ax_ler, ax_moy, ax_moy_30j]:
ax.legend().set_visible(False)
fig.legend(bbox_to_anchor=(1, 0), loc="lower right",
bbox_transform=fig.transFigure, ncol=4)
fig.legend(loc='lower center', ncol=2)
# on enlève ax_codemois de la liaison
# https://stackoverflow.com/questions/42973223/how-to-share-x-axes-of-two-subplots-after-they-have-been-created
ax_codemois.autoscale()
ax_codemois.axis('off')
handles = [Line2D([0], [0], marker='*', ls="None", label=DICO_NOM_MOIS[mois],markerfacecolor=DICO_COULEURS_MOIS[mois],
markeredgecolor=DICO_COULEURS_MOIS[mois], markersize=7) for mois in range(1, 13)]
ax_codemois.legend(handles=handles, ncol=6, title="Code couleur des mois", fontsize=9, title_fontsize=9,
labelspacing=1.5)
ax_ler.format_ydata = un_chiffre_apres_la_virgule
ax_moy.format_ydata = un_chiffre_apres_la_virgule
ax_moy_30j.format_ydata = un_chiffre_apres_la_virgule
#le module pickle
# nom_fichier_pickle = Path(nom_fichier).with_suffix('.pickle')
# pl.dump(fig, open(nom_fichier_pickle, 'wb'))
# print(nom_fichier_pickle)
# plt.gca().format_xdata = mpldates.DateFormatter('%Y/%m')
# plt.gca().format_ydata = un_chiffre_apres_la_virgule
# plt.gcf().autofmt_xdate() # sur figure
plt.show()
# pas d'instruction return, mais par défaut la fonction retourne quand même... None
# LIRE UN FICHIER BINAIRE
def lire_lame_deau_radar_5min(nom_fichier_binaire):
PDT_OBS_EN_MIN = 5
DIVISEUR = 10
CODE_LACUNE_BINAIRE = 65535 # => -999.99 (lacune)
CODE_LACUNE = -999.99
nb_of_days = 3653
pas_de_temps = 24 * 60 / PDT_OBS_EN_MIN # nb de pas de temps dans une journée ; = 288
# nb_valeurs_cp = nb_of_days * pas_de_temps = 1514972160
len_of_tvect = nb_of_days * pas_de_temps # 1052064
recordSize = len_of_tvect * 2 # parce que ce sont des entiers codés sur 2 bytes
date_premiere_valeur = datetime(2006, 7, 1, 0, 5)
liste_dates = [date_premiere_valeur + i * timedelta(minutes=PDT_OBS_EN_MIN) for i in
range(len_of_tvect)] # PDT_OBS_EN_MIN = 5 minutes
if Path.is_file(Path(nom_fichier_binaire)):
print(f"nom_chemin_binaire1 : {nom_fichier_binaire} ")
# lecture des valeurs
# cf fonctions Chronique.lire_chronique Lecture_Patnthere...chronique
uint16_valeurs = None
with open(nom_fichier_binaire, 'rb') as fic_binaire:
try:
uint16_valeurs = np.fromfile(fic_binaire, dtype=np.uint16, count=int(len(liste_dates)))
statut_lecture = "OK"
except:
statut_lecture = "erreur"
# VERIF
print("Ensemble des valeurs lues avant traitement (lacunes, diviseur...) : ", set(uint16_valeurs))
if statut_lecture == "OK":
# Traitement des lacunes
nb_lacunes = 0
for valeur in uint16_valeurs:
if int(valeur) == int(CODE_LACUNE_BINAIRE):
nb_lacunes += 1
print("Nombre de lacunes = ", nb_lacunes)
# on travaille avec des LAMES D'EAU en centième de mm, à passer en mm
np_valeurs = np.array(
[entier / DIVISEUR if entier != int(CODE_LACUNE_BINAIRE) else np.nan for entier in
uint16_valeurs])
# tracé
debut = datetime.now()
plt.step(liste_dates, np_valeurs)
plt.title("Fichier binaire "+ os.path.basename(nom_fichier_binaire) + "\n sans précaution pour les étiquettes de dates" )
temps = datetime.now() - debut
plt.show()
plt.close()
print("temps écoulé, step:", temps)
def trace_3_courbes_avec_pandas(ts_lamedeau, ts_mensuel, ts_journalier):
print("Moyennes pdt fixes")
fig = plt.figure("Chroniques_pandas", figsize=[10, 5]) # tight_layout=True,
fig.suptitle("Avec pandas, plus moyennes mensuelles en errorbars")
# https://matplotlib.org/gallery/userdemo/demo_gridspec03.html#sphx-glr-gallery-userdemo-demo-gridspec03-py
gs = gridspec.GridSpec(nrows=2, ncols=1, height_ratios=[10, 1])
ax1 = fig.add_subplot(gs[0])
# ax1 = df_lamedeau.loc[:, cols[1]].plot(label=cols[1],
# title="Avec pandas, données moyennées (pas de temps fixe)",
# color='purple')
ts_lamedeau.plot(label="lame d'eau à 5 min", color='purple', ax=ax1)
(handles1, labels1) = ax1.get_legend_handles_labels()
return liste_dates, np_valeurs
ax2 = ax1.twinx()
# Tracer une longue série, applicable à toutes donnnées (lues dans Hydro2, dans un binaire ou tout autre format)
def tracer_proprement_une_longue_serie(dates, valeurs, info_chroniques="lames d'eau radar, mm en 5 min"):
""" démonstration de "concise formatter"
moyenne_des_mois = ts_mensuel.mean()
moyenne_des_ler5min = ts_lamedeau.mean()
print("moyenne des mois = ", moyenne_des_mois, " à comparer avec ", moyenne_des_ler5min)
"""
locator = mdates.AutoDateLocator(minticks=3, maxticks=12)
formatter = mdates.ConciseDateFormatter(locator)
ts_mensuel.plot(label=' cumul mensuel', color='lightblue', ax=ax2, ls=':')
ax2.errorbar(ts_mensuel.index, ts_mensuel, label=' cumul mensuel avec figuré errorbar', xerr=timedelta(days=30),
ls='None', color='blue', marker=">", xuplims=True)
# VERIF
if len(dates) != len(valeurs):
print(f"Les 2 vecteurs n'ont pas la même longueur : {len(dates)} dates et {len(valeurs)} valeurs")
return
# ça permet de quitter la fonction ; ce n'est pas la meilleure manière de faire (plutôt un else...)
debut_pour_plt = pd.to_datetime(date_debut_pd)
fin_pour_plt = pd.to_datetime(date_fin_pd)
print("Nombre de points : ", len(dates))
# TESTS AVEC LES VLINE avec s
# ts_journalier.plot(label=' moyenne journalière', color='orange', ax=ax2)
# https: // stackoverflow.com / questions / 5902371 / matplotlib - bar - chart - with-dates
# ax1.xaxis_date()
ts_journalier.plot(label=' moyenne journalière', color='orange', ax=ax2)
(handles2, labels2) = ax2.get_legend_handles_labels()
# tracé
debut = datetime.now()
plt.ion()
fig_cf, ax_t = plt.subplots()
fig_cf.suptitle("Tracé d'une longue chronique, soin apporté aux étiquettes de dates \n" + info_chroniques)
ax_t.set_xlabel("dates, format date", fontsize=14)
ax_t.set_ylabel("info_valeurs", fontsize=14)
ax_t.xaxis.set_major_locator(locator)
ax_t.xaxis.set_major_formatter(formatter)
ax_t.step(dates, valeurs)
plt.legend(handles1 + handles2, labels1 + labels2, bbox_to_anchor=(0.9, 0.05), loc="lower right", # mode="expand",
bbox_transform=fig.transFigure, ncol=2) # loc='best')
temps = datetime.now() - debut
print("tracer_proprement_une_longue_serie, temps écoulé, step:", temps)
fig_cf.canvas.draw()
fig_cf.savefig("test.png")
plt.ioff()
plt.show()
# plt.clf()
def trace_3_courbes_avec_pandas_donc_vlines(ts_lamedeau, ts_mensuel, ts_journalier):
print("Moyennes pdt fixes, trace_3_courbes_avec_pandas_dont_vlines")
#plt.close()
# ax1 = df_lamedeau.loc[:, cols[1]].plot(label=cols[1],
# title="Avec pandas, données moyennées (pas de temps fixe)",
# color='purple')
# on ne retourne rien
fig = plt.figure("avec_pandas_jours_vlines", tight_layout=True)
gs = gridspec.GridSpec(nrows=2, ncols=1, height_ratios=[10, 1])
ax1 = fig.add_subplot(gs[0])
ts_lamedeau.plot(label="lame d'eau à 5 min", title="Avec pandas et vlines", color='purple', ax=ax1)
(handles, labels) = ax1.get_legend_handles_labels()
def tracer_une_longue_serie_en3_resolutions_tests(dates, valeurs, info_chroniques=" série temporelle", info_valeurs="lames d'eau radar, mm en 5 min"):
# met en lumière des problèmes liés à pandas.resample
# pour les données binaires, voir en particulier le pic max, situé un 30 juin à 17h30, avec une max mensuel rebasculé au mois suivant
ax2 = ax1.twinx()
locator = mdates.AutoDateLocator(minticks=3, maxticks=12)
formatter = mdates.ConciseDateFormatter(locator)
# ts_journalier.plot(label=' moyenne journalière', color='orange', ax=ax2)
# https: // stackoverflow.com / questions / 5902371 / matplotlib - bar - chart - with-dates
# ax1.xaxis_date()
couleur_originale = 'purple'
dico_resolutions = {"jour":"1D", "mois":"1M", "année":"1Y"}
dico_resolutions_couleurs = {"jour": "blue", "mois": "green", "année": "orange"}
moyenne_des_mois = ts_mensuel.mean()
print("moyenne des mois = ", moyenne_des_mois)
fig, (ax_original, ax_resample_max) = plt.subplots(nrows=2, ncols=1, sharex=True)
fig.subplots_adjust(bottom=0.3)
# graphique des mois
ts_mensuel.plot(label=' cumuls mensuels (pd plot)', color='lightblue', ax=ax2)
ax2.errorbar(ts_mensuel.index, ts_mensuel, label='cumuls mensuels (figuré errorbar)', xerr=timedelta(days=30),
ls='None', color='blue', marker=">", xuplims=True)
fig.suptitle(info_valeurs + "\n Rééchantillonnages sur pdt fixes, en utilisant pandas")
ax_resample_moy = ax_original.twinx()
ax_original.set_ylabel("Données originales", color=couleur_originale)
ax_resample_moy.set_ylabel("Moyennes sur pdt fixes", color='black')
ax_resample_max.set_ylabel("Max sur pdt fixes", color='black')
# méthode plot de pandas appliquée à un dataframe
debut_pour_plt = pd.to_datetime(date_debut_pd)
fin_pour_plt = pd.to_datetime(date_fin_pd)
ax_original.step(dates, valeurs, c=couleur_originale, label="résolution du fichier")
#ax_original.plot(dates, valeurs, c=couleur_originale, label="résolution du fichier", marker='*', markersize=10, ls="None")
ax_original.legend()
ts= pd.Series(data=valeurs, index=dates, name=info_valeurs)
# test d'un axe supplémentaire (3e) avec twinx : il va être superposé à l'axe déjà défini par twinx
if False:
ax_test = ax_original.twinx()
ax_test.set_ylabel("test", color="sienna")
ts_test = ts.resample('1D', closed='left').mean()
ax_test.plot(ts_test.index.to_pydatetime(), ts_test.to_numpy(), c='sienna',
label="test", marker='None', ls="None")
# on définit une liste ax_moy dans le cas où l'on veut tester un "ax" par résolution : résultat, les axes des y sont superposés
#ax_moy=[]
for duree, reso in dico_resolutions.items():
ts_moy = ts.copy().resample(reso, closed='left',label='left').mean()
#ax_moy.append(ax_original.twinx())
print(f"Rééchantillonnage par moyenne sur pas de temps {duree}, première date = {ts_moy.index[0]}")
# ax_resample_moy.step(ts_moy.index, ts_moy.to_numpy(), c=dico_resolutions_couleurs[duree], label=duree)
ax_resample_moy.plot(ts_moy.index.to_pydatetime(), ts_moy.to_numpy(), c=dico_resolutions_couleurs[duree],
label=duree, marker='*', ls="None")
if reso=="1D":
ax_resample_moy.step(ts_moy.index.to_pydatetime(), ts_moy.to_numpy(), c=dico_resolutions_couleurs[duree],
label=duree, where='post')
else:
ax_resample_moy.step(ts_moy.index.to_pydatetime(), ts_moy.to_numpy(), c=dico_resolutions_couleurs[duree],
label=duree)
"""
ax_moy[-1].plot(ts_moy.index.to_pydatetime(), ts_moy.to_numpy(), c=dico_resolutions_couleurs[duree],
label=duree, marker='*', ls="None")
ax_moy[-1].step(ts_moy.index.to_pydatetime(), ts_moy.to_numpy(), c=dico_resolutions_couleurs[duree], label=duree) # , where='post')
"""
ts_max = ts.resample(reso, closed='left', label='left').max()
print(f"Rééchantillonnage par max sur pas de temps {duree}, première date = {ts_max.index[0]}")
# ax_resample_max.step(ts_max.index, ts_max.to_numpy(), c=dico_resolutions_couleurs[duree], label=duree)
ax_resample_max.plot(ts_max.index.to_pydatetime(), ts_max.to_numpy(), c=dico_resolutions_couleurs[duree],
label=duree, marker='*', ls="None")
if reso=="1D":
ax_resample_max.step(ts_max.index.to_pydatetime(), ts_max.to_numpy(), c=dico_resolutions_couleurs[duree], label=duree, where='post')
else:
ax_resample_max.step(ts_max.index.to_pydatetime(), ts_max.to_numpy(), c=dico_resolutions_couleurs[duree],
label=duree)
# TESTS AVEC LES AX.H/V.LINE avec s
# il faut un autre plot déjà sur le même ax
# ts_journalier.plot(label=' moyenne journalière', color='orange', ax=ax2, ls=':')
ax2.vlines(x=ts_journalier.index, ymin=0, ymax=ts_journalier, label="cumuls journaliers (vlines)", color='orange',
lw=5, alpha=0.8)
# PB avec STEM :
# ValueError: view limit minimum -453626.8500000001 is less than 1 and is an invalid Matplotlib date value. This often happens if you pass a non-datetime value to an axis that has datetime units
# + stem() got an unexpected keyword argument 'use_line_collection'
# on teste d'abord avec les mois ??
# ax2.stem(ts_journalier.index, ts_journalier) # use_line_collection=True) #, color='red')
# print(type(ts_mensuel.index[0]))
# print(ts_mensuel.index)
# ax2.stem([pd.to_datetime(date) for date in ts_mensuel.index], ts_mensuel)
ax_resample_max.legend()
(handles2, labels2) = ax2.get_legend_handles_labels()
ax_original.xaxis.set_major_locator(locator)
ax_original.xaxis.set_major_formatter(formatter)
plt.legend(handles + handles2, labels + labels2, bbox_to_anchor=(1, 0.1), loc="lower right", # mode="expand",
bbox_transform=fig.transFigure, ncol=2) # loc='best')
plt.show()
# plt.clf()
# moyennes par MOIS avec des rectangles
def trace_mensuel_avec_rectangles(ts_lamedeau, ts_mensuel, ts_journalier=None, trace_rect_mensuels=False):
debut = datetime.now()
def tracer_une_longue_serie_en3_resolutions_mieux(dates, valeurs, info_chroniques="lames d'eau radar, mm en 5 min"):
"""
si DF
ax1 = df_lamedeau.loc[:, cols[1]].plot(label=cols[1],
title="Avec rectangles,5 min et cumuls mensuels (pas de temps fixe)",
color='purple', zorder=10)
solutions proposées au pb identifié
"""
fig, ax1 = plt.subplots("chroniques_mois_rectangles", figsize=(7, 4))
ts_lamedeau.plot(title="trace_mensuel_avec_rectangles (cumuls pas de temps fixe)", label="lames d'eau à 5 min",
color='purple', zorder=10, ax=ax1)
ax1.set(ylabel="Lames d'eau à 5 min")
(handles, labels) = plt.gca().get_legend_handles_labels()
# pas possible de mettre un 2e axe rien qu'avec des rectangles... DONC il faut mettre une ligne "guide" avec un plot
# moyenne_des_mois = ds_mensuel["lames d'eau en mm"].mean()
date_debut_pd = ts_lamedeau.index[0]
date_fin_pd = ts_lamedeau.index[-1]
ax2 = ax1.twinx()
ts_debutfin = pd.Series([ts_mensuel.mean(), ts_mensuel.mean()], index=[date_debut_pd, date_fin_pd])
ts_debutfin.plot(ls=':', label='moyenne des cumuls mensuels', ax=ax2)
ax2.set(ylabel="cumuls (sur la durée, 1 j ou 1 mois)")
for debut_rect, valeur in zip(ts_mensuel.index, ts_mensuel):
if debut_rect.month in [12, 1, 2]:
code_couleur = 'blue'
elif debut_rect.month in [3, 4, 5]:
code_couleur = 'pink'
elif debut_rect.month in [6, 7, 8]:
code_couleur = 'yellow'
else:
code_couleur = 'orange'
print(debut_rect, valeur, code_couleur)
# patch = patches.Rectangle(xy, w, h, linewidth=1, edgecolor=edgecolor, facecolor=facecolor)
if trace_rect_mensuels:
ax2.add_patch(Rectangle((debut_rect, 0.1), -timedelta(days=30), valeur, color=code_couleur, alpha=0.8))
# pause=input("fin des rectangles par mois ! ")
"""
# avec PatchCollection (pb avec dates ??)
notre_cmap = ListedColormap(color_list)
patches_collection = PatchCollection(patch_list, cmap=notre_cmap, alpha=1)
patches_collection.set_array(np.arange(len(patch_list)))
ax1.add_collection(patches_collection, zorder=5)
"""
ts_journalier.plot(color='red', ax=ax2, label='cumul journalier')
(handles2, labels2) = plt.gca().get_legend_handles_labels()
# ax1.plot(ts_journalier.index, ts_journalier, label=' pyplot',
# ls=':', color='yellow', lw=5, alpha=0.5)
# ax1.errorbar(ts_journalier.index, ts_journalier, label=' moyenne journalière par errorbar', xerr=timedelta(days=1),
# ls='None', color='orange', marker=">", xuplims=True)
# Legende commune
# plt.gca().legend(handles+handles2,labels+labels2)
box = plt.gca().get_position()
plt.gca().set_position([box.x0, box.y0, box.width * 0.8, box.height])
fig.legend(loc=7)
# max_valeur = max(df_lamedeau["lames d'eau en mm"].max(), df_mensuel["lames d'eau en mm"].max())
# min_valeur = min(0, df_lamedeau["lames d'eau en mm"].min(), df_mensuel["lames d'eau en mm"].min())
# ax1.set_ylim(min_valeur, df_mensuel["lames d'eau en mm"].max()*1.1)
# ax1.set_ylim(min_valeur, max_valeur * 1.1)
ax1.set_ylim(0, ts_lamedeau.max() * 1.1)
ax2.set_ylim(0, ts_mensuel.max() * 1.1)
# jours : Memoruy Error avec vlines ?
"""
color_list = []
for debut_rect, valeur in zip(df_journalier.index, df_journalier["lames d'eau en mm"]):
if debut_rect.month in [12, 1, 2]:
code_couleur = 'blue'
elif debut_rect.month in [3, 4, 5]:
code_couleur = 'pink'
elif debut_rect.month in [6, 7, 8]:
code_couleur = 'yellow'
else:
code_couleur = 'orange'
# format the coords message box
def un_chiffre_apres_la_virgule(x):
# return '%1.1f unités' % x
return f"{x:.1f} mm/5 min"
color_list.append(code_couleur)
# imports spécifiques
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA
locator = mdates.AutoDateLocator(minticks=3, maxticks=12)
formatter = mdates.ConciseDateFormatter(locator)
fig = plt.figure(dpi=100) # , frameon=False figsize=(20, 4),
fig.patch.set_facecolor('white')
fig.subplots_adjust(right=0.75, bottom=0.15) # on définit des marges
fig.suptitle(info_chroniques + "\n Rééchantillonnages sur pdt fixes, en utilisant pandas")
# VIGNETTE DU HAUT
host_original = host_subplot(211, axes_class=AA.Axes)
par_j = host_original.twinx()
par_m = host_original.twinx()
par_a = host_original.twinx()
offset = 40
new_fixed_axis_j = par_j.get_grid_helper().new_fixed_axis
par_j.axis["right"] = new_fixed_axis_j(loc="right", axes=par_j, offset=(0, 0))
par_j.axis["right"].toggle(all=True)
new_fixed_axis_m = par_m.get_grid_helper().new_fixed_axis
par_m.axis["right"] = new_fixed_axis_m(loc="right", axes=par_m, offset=(offset, 0))
par_m.axis["right"].toggle(all=True)
new_fixed_axis_a = par_a.get_grid_helper().new_fixed_axis
par_a.axis["right"] = new_fixed_axis_a(loc="right", axes=par_a, offset=(2*offset, 0))
par_a.axis["right"].toggle(all=True)
# vignette du bas
ax_unique = fig.add_subplot(212, sharex =host_original)
# tracé donnée à la résolution originale,
ts = pd.Series(data=valeurs, index=dates, name=info_chroniques)
couleur_originale = 'purple'
host_original.set_ylabel("Données originales", color=couleur_originale)
host_original.step(dates, valeurs, c=couleur_originale)
ax_unique.set_ylabel("Max sur pas de temps fixe", color='black')
ax_unique.step(dates, valeurs, c=couleur_originale, label="résolution du fichier")
dico_resolutions = {"jour":"1D", "mois":"1M", "année":"1Y"}
dico_resolutions_couleurs = {"jour": "blue", "mois": "green", "année": "orange"}
# vignette du haut, moyennes
par_j.set_ylabel("Moyennes journalières", color=dico_resolutions_couleurs["jour"])
par_m.set_ylabel("Moyennes mensuelles", color=dico_resolutions_couleurs["mois"])
par_a.set_ylabel("Moyennes annuelles", color=dico_resolutions_couleurs["année"])
ts_j_moy = ts.resample("1D").mean()
print(f"Rééchantillonnage par moyenne sur pas de temps {'jour'}, première date = {ts_j_moy.index[0]}")
par_j.plot(ts_j_moy.index.to_pydatetime(), ts_j_moy.to_numpy(), c=dico_resolutions_couleurs["jour"],
marker='*', ls="None")
par_j.step(ts_j_moy.index.to_pydatetime(), ts_j_moy.to_numpy(), c=dico_resolutions_couleurs["jour"],
label="jour", where='post')
ts_m_moy = ts_j_moy.resample("1M").mean()
print(f"Rééchantillonnage par moyenne sur pas de temps {'mois'}, première date = {ts_m_moy.index[0]}")
par_m.plot(ts_m_moy.index.shift(1, freq='D').to_pydatetime(), ts_m_moy.to_numpy(), c=dico_resolutions_couleurs["mois"],
marker='*', ls="None")
par_m.step(ts_m_moy.index.shift(1, freq='D').to_pydatetime(), ts_m_moy.to_numpy(), c=dico_resolutions_couleurs["mois"],
label="mois")
ts_a_moy = ts_m_moy.resample("1Y").mean()
print(f"Rééchantillonnage par moyenne sur pas de temps {'année'}, première date = {ts_a_moy.index[0]}")
par_a.plot(ts_a_moy.index.shift(1, freq='D').to_pydatetime(), ts_a_moy.to_numpy(), c=dico_resolutions_couleurs["année"],
marker='*', ls="None")
par_a.step(ts_a_moy.index.shift(1, freq='D').to_pydatetime(), ts_a_moy.to_numpy(), c=dico_resolutions_couleurs["année"],
label="année")
# vignette du bas, max
ts_j_max = ts.resample("1D").max()
print(f"Rééchantillonnage par max sur pas de temps {'jour'}, première date = {ts_j_moy.index[0]}")
# ax_resample_moy.step(ts_moy.index, ts_moy.to_numpy(), c=dico_resolutions_couleurs[duree], label=duree)
ax_unique.plot(ts_j_max.index.to_pydatetime(), ts_j_max.to_numpy(), c=dico_resolutions_couleurs["jour"],
marker='*', ls="None")
ax_unique.step(ts_j_max.index.to_pydatetime(), ts_j_max.to_numpy(), c=dico_resolutions_couleurs["jour"],
where='post')
ts_m_max = ts_j_max.resample("1M").max()
print(f"Rééchantillonnage par max sur pas de temps {'mois'}, première date = {ts_m_moy.index[0]}")
# ax_resample_moy.step(ts_moy.index, ts_moy.to_numpy(), c=dico_resolutions_couleurs[duree], label=duree)
ax_unique.plot(ts_m_max.index.shift(1, freq='D').to_pydatetime(), ts_m_max.to_numpy(), c=dico_resolutions_couleurs["mois"],
marker='*', ls="None")
ax_unique.step(ts_m_max.index.shift(1, freq='D').to_pydatetime(), ts_m_max.to_numpy(), c=dico_resolutions_couleurs["mois"])
ts_a_max = ts_m_max.resample("1Y").max()
print(f"Rééchantillonnage par max sur pas de temps {'année'}, première date = {ts_a_moy.index[0]}")
ax_unique.plot(ts_a_max.index.shift(1, freq='D').to_pydatetime(), ts_a_max.to_numpy(), c=dico_resolutions_couleurs["année"],
marker='*', ls="None")
ax_unique.step(ts_a_max.index.shift(1, freq='D').to_pydatetime(), ts_a_max.to_numpy(), c=dico_resolutions_couleurs["année"])
host_original.xaxis.set_major_locator(locator)
host_original.xaxis.set_major_formatter(formatter)
fig.legend(loc='lower center', ncol=4)
host_original.format_ydata = un_chiffre_apres_la_virgule
# colors avec un s car il y a une liste
ax2.vlines(df_journalier.index, 0, df_journalier["lames d'eau en mm"], colors=color_list)
"""
temps = datetime.now() - debut
plt.show()
print("temps écoulé Pandas avec mois en rectangles", temps)
# plt.close(fig)
def trace_mensuel_avec_hlines(ts_lamedeau, ts_mensuel, ts_journalier=None, trace_hlines=False):
debut = datetime.now()
def tracer_une_longue_serie_lame_deau_en3_resolutions_verifs(dates, valeurs, info_resolution_min=5, couverture_mini = 0.8, info_chroniques="lames d'eau radar, mm en 5 min"):
"""
si DF
ax1 = df_lamedeau.loc[:, cols[1]].plot(label=cols[1],
title="Avec rectangles,5 min et cumuls mensuels (pas de temps fixe)",
color='purple', zorder=10)
Cas de lames d'eau : on aggrège par CUMUL
solutions proposées au pb identifié :
+ boucle "propre", possible car on ne distingue plus le cas journalier des autres
+ vérif nb points disponibles avec resample().count
https://stackoverflow.com/questions/49019245/resample-pandas-with-minimum-required-number-of-observations
todo : reste un défaut, les 0 ne sont pas forcément alignés sur la même horizontale !
"""
fig = plt.figure(figsize=(7, 4))
# on crée un emplacement vide
gs = gridspec.GridSpec(nrows=2, ncols=1, height_ratios=[10, 1])
ax1 = fig.add_subplot(gs[0])
ts_lamedeau.plot(title="tracé cumuls_mensuel_avec_hlines ", label="lames d'eau à 5 min", color='purple',
zorder=10, ax=ax1)
ax1.set(ylabel="Lames d'eau à 5 min")
(handles, labels) = plt.gca().get_legend_handles_labels()
# pas possible de mettre un 2e axe rien qu'avec des rectangles... DONC il faut mettre une ligne "guide" avec un plot
# moyenne_des_mois = ds_mensuel["lames d'eau en mm"].mean()
date_debut_pd = ts_lamedeau.index[0]
date_fin_pd = ts_lamedeau.index[-1]
ax2 = ax1.twinx()
ts_debutfin = pd.Series([ts_mensuel.mean(), ts_mensuel.mean()], index=[date_debut_pd, date_fin_pd])
ts_debutfin.plot(ls=':', label='moyenne des cumuls mensuels', ax=ax2)
ax2.set(ylabel="cumuls (sur la durée, 1 j ou 1 mois)")
# format the coords message box
def un_chiffre_apres_la_virgule(x):
# return '%1.1f unités' % x
return f"{x:.1f} mm/5 min"
codes_couleur = []
for debut_rect, valeur in zip(ts_mensuel.index, ts_mensuel):
if debut_rect.month in [12, 1, 2]:
code_couleur = 'blue'
elif debut_rect.month in [3, 4, 5]:
code_couleur = 'pink'
elif debut_rect.month in [6, 7, 8]:
code_couleur = 'yellow'
# imports spécifiques
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA
locator = mdates.AutoDateLocator(minticks=3, maxticks=12)
formatter = mdates.ConciseDateFormatter(locator)
fig = plt.figure(dpi=100) # , frameon=False figsize=(20, 4),
fig.patch.set_facecolor('white')
fig.subplots_adjust(right=0.75, bottom=0.15) # on définit des marges
fig.suptitle(info_chroniques + f"\n Rééchantillonnages sur pdt fixes, taux de couverture mini = {int(couverture_mini*100)}%")
# VIGNETTE DU HAUT
host_original = host_subplot(211, axes_class=AA.Axes)
par_j = host_original.twinx()
par_m = host_original.twinx()
par_a = host_original.twinx()
offset = 40
new_fixed_axis_j = par_j.get_grid_helper().new_fixed_axis
par_j.axis["right"] = new_fixed_axis_j(loc="right", axes=par_j, offset=(0, 0))
par_j.axis["right"].toggle(all=True)
new_fixed_axis_m = par_m.get_grid_helper().new_fixed_axis
par_m.axis["right"] = new_fixed_axis_m(loc="right", axes=par_m, offset=(offset, 0))
par_m.axis["right"].toggle(all=True)
new_fixed_axis_a = par_a.get_grid_helper().new_fixed_axis
par_a.axis["right"] = new_fixed_axis_a(loc="right", axes=par_a, offset=(2*offset, 0))
par_a.axis["right"].toggle(all=True)
# vignette du bas
ax_unique = fig.add_subplot(212, sharex =host_original)
# tracé donnée à la résolution originale,
ts = pd.Series(data=valeurs, index=dates, name=info_chroniques)
couleur_originale = 'purple'
host_original.set_ylabel("Données originales", color=couleur_originale)
host_original.step(dates, valeurs, c=couleur_originale)
ax_unique.set_ylabel("Max sur pas de temps fixe", color='black')
ax_unique.step(dates, valeurs, c=couleur_originale, label="résolution du fichier")
dico_resolutions = {"jour":"1D", "mois":"1M", "année":"1Y"}
dico_resolutions_couleurs = {"jour": "blue", "mois": "green", "année": "orange"}
# vignette du haut, moyennes
par_j.set_ylabel("Cumuls journaliers", color=dico_resolutions_couleurs["jour"])
par_m.set_ylabel("Cumuls mensuels", color=dico_resolutions_couleurs["mois"])
par_a.set_ylabel("Cumuls annuels", color=dico_resolutions_couleurs["année"])
nb_minutes_attendues_par_jour = couverture_mini * 24*60 / info_resolution_min
for ((reso, code_reso), axe_parasite) in zip(dico_resolutions.items(), [par_j, par_m, par_a]):
# vignette du haut, moyennes
df_reso_moy = ts.resample(code_reso).agg(['sum', 'count']) # une colonne moyenne, une colonne nombre de points dans la fenêtre
# définition d'un "masque" de booléens par une condition
if reso=="jour":
invalid = df_reso_moy['count'] <= nb_minutes_attendues_par_jour
elif reso=="mois":
invalid = df_reso_moy['count'] <= df_reso_moy.index.days_in_month * nb_minutes_attendues_par_jour
else:
code_couleur = 'orange'
invalid = df_reso_moy['count'] <= 365 * nb_minutes_attendues_par_jour
codes_couleur.append(code_couleur)
# restrict to the sum and null out invalid entries, using invalid as a mask
# https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
df_reso_moy.loc[invalid, 'sum'] = np.nan
ts_reso_moy = df_reso_moy['sum']
print(f"Rééchantillonnage par moyenne sur pas de temps {reso}, première date = {ts_reso_moy.index[0]}")
axe_parasite.plot(ts_reso_moy.index.shift(1, freq='D').to_pydatetime(), ts_reso_moy.to_numpy(), c=dico_resolutions_couleurs[reso],
marker='*', ls="None")
axe_parasite.step(df_reso_moy.index.shift(1, freq='D').to_pydatetime(), ts_reso_moy.to_numpy(), c=dico_resolutions_couleurs[reso],
label=reso) # , where='post')
print(debut_rect, valeur, code_couleur)
# vignette du bas, max
if trace_hlines:
ax2.hlines(y=ts_mensuel, xmax=ts_mensuel.index,
xmin=[date - timedelta(days=30) for date in ts_mensuel.index],
label="cumuls mensuels", color=codes_couleur, lw=3, alpha=0.8)
ts_reso_max = ts.resample(code_reso).max()
ts_reso_max[invalid] = np.nan
print(f"Rééchantillonnage par max sur pas de temps {'jour'}, première date = {ts_reso_max[0]}")
ax_unique.plot(ts_reso_max.index.shift(1, freq='D').to_pydatetime(), ts_reso_max.to_numpy(), c=dico_resolutions_couleurs[reso],
marker='*', ls="None")
ax_unique.step(ts_reso_max.index.shift(1, freq='D').to_pydatetime(), ts_reso_max.to_numpy(), c=dico_resolutions_couleurs[reso])
ts_journalier.plot(color='red', ax=ax2, label='cumuls journaliers')
(handles2, labels2) = plt.gca().get_legend_handles_labels()
host_original.xaxis.set_major_locator(locator)
host_original.xaxis.set_major_formatter(formatter)
# Legende commune
fig.legend(loc='lower center', ncol=4)
plt.legend(handles + handles2, labels + labels2, bbox_to_anchor=(1, 0.01), loc="lower right", # mode="expand",
bbox_transform=fig.transFigure, ncol=2)
"""
box = plt.gca().get_position()
plt.gca().set_position([box.x0, box.y0, box.width * 0.8, box.height])
fig.legend(loc=7)
"""
ax1.set_ylim(0, ts_lamedeau.max() * 1.1)
ax2.set_ylim(0, ts_mensuel.max() * 1.1)
host_original.format_ydata = un_chiffre_apres_la_virgule
temps = datetime.now() - debut
plt.show()
print("temps écoulé Pandas avec mois en rectangles", temps)
# plt.clf()
def HautBas_trace_mensuel_avec_rectangles(ts_lamedeau, ts_mensuel, ts_journalier=None, trace_rect_mensuels=False):
debut = datetime.now()
def tracer_une_longue_serie_q_en3_resolutions_verifs(dates, valeurs, info_resolution_min=60, couverture_mini = 0.8, info_chroniques="débit moyen sur une journée"):
"""
si DF
ax1 = df_lamedeau.loc[:, cols[1]].plot(label=cols[1],
title="Avec rectangles,5 min et cumuls mensuels (pas de temps fixe)",
color='purple', zorder=10)
"""
# d'après cheatsheet pbpython
fig, (ax_cumul, ax_5min) = plt.subplots(nrows=2, ncols=1, sharex=True, figsize=(7, 4))
fig.suptitle("Lames d'eau à 5 min (bas) et cumuls journaliers et mensuels (haut)")
ax_cumul.set(ylabel="cumuls")
ax_5min.set(ylabel="lame d'eau \n à 5 min")
ts_lamedeau.plot(label="lames d'eau à 5 min", color='purple', zorder=10, ax=ax_5min)
plt.legend()
Cas de débits : on aggrège par MOYENNE
solutions proposées au pb identifié :
+ boucle "propre", possible car on ne distingue plus le cas journalier des autres
+ vérif nb points disponibles avec resample().count
# pas possible de mettre un 2e axe rien qu'avec des rectangles... DONC il faut mettre une ligne "guide" avec un plot
# moyenne_des_mois = ds_mensuel["lames d'eau en mm"].mean()
date_debut_pd = ts_lamedeau.index[0]
date_fin_pd = ts_lamedeau.index[-1]
https://stackoverflow.com/questions/49019245/resample-pandas-with-minimum-required-number-of-observations
todo : reste un défaut, les 0 ne sont pas forcément alignés sur la même horizontale !
"""
ts_debutfin = pd.Series([ts_mensuel.mean(), ts_mensuel.mean()], index=[date_debut_pd, date_fin_pd])
ts_debutfin.plot(ls=':', label='moyenne des cumuls mensuels', ax=ax_cumul)
# format the coords message box
def un_chiffre_apres_la_virgule(x):
# return '%1.1f unités' % x
return f"{x:.1f} mm/5 min"
# TESTS : on enlève les rectangles
for debut_rect, valeur in zip(ts_mensuel.index, ts_mensuel):
if debut_rect.month in [12, 1, 2]:
code_couleur = 'blue'
elif debut_rect.month in [3, 4, 5]:
code_couleur = 'pink'
elif debut_rect.month in [6, 7, 8]:
code_couleur = 'yellow'
# imports spécifiques
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA
locator = mdates.AutoDateLocator(minticks=3, maxticks=12)
formatter = mdates.ConciseDateFormatter(locator)
fig = plt.figure(dpi=100) # , frameon=False figsize=(20, 4),
fig.patch.set_facecolor('white')
fig.subplots_adjust(right=0.75, bottom=0.15) # on définit des marges
fig.suptitle(info_chroniques + f"\n Rééchantillonnages sur pdt fixes, taux de couverture mini = {int(couverture_mini*100)}%")
# VIGNETTE DU HAUT
host_original = host_subplot(211, axes_class=AA.Axes)
par_j = host_original.twinx()
par_m = host_original.twinx()
par_a = host_original.twinx()
offset = 40
new_fixed_axis_j = par_j.get_grid_helper().new_fixed_axis
par_j.axis["right"] = new_fixed_axis_j(loc="right", axes=par_j, offset=(0, 0))
par_j.axis["right"].toggle(all=True)
new_fixed_axis_m = par_m.get_grid_helper().new_fixed_axis
par_m.axis["right"] = new_fixed_axis_m(loc="right", axes=par_m, offset=(offset, 0))
par_m.axis["right"].toggle(all=True)
new_fixed_axis_a = par_a.get_grid_helper().new_fixed_axis
par_a.axis["right"] = new_fixed_axis_a(loc="right", axes=par_a, offset=(2*offset, 0))
par_a.axis["right"].toggle(all=True)
# vignette du bas
ax_unique = fig.add_subplot(212, sharex =host_original)
# tracé donnée à la résolution originale,
ts = pd.Series(data=valeurs, index=dates, name=info_chroniques)
couleur_originale = 'purple'
host_original.set_ylabel("Données originales", color=couleur_originale)
host_original.step(dates, valeurs, c=couleur_originale)
ax_unique.set_ylabel("Max sur pas de temps fixe", color='black')
ax_unique.step(dates, valeurs, c=couleur_originale, label="résolution du fichier")
dico_resolutions = {"jour":"1D", "mois":"1M", "année":"1Y"}
dico_resolutions_couleurs = {"jour": "blue", "mois": "green", "année": "orange"}
# vignette du haut, moyennes
par_j.set_ylabel("Moyennes journalières", color=dico_resolutions_couleurs["jour"])
par_m.set_ylabel("Moyennes mensuelles", color=dico_resolutions_couleurs["mois"])
par_a.set_ylabel("Moyennes annuelles", color=dico_resolutions_couleurs["année"])
nb_minutes_attendues_par_jour = couverture_mini * 24*60 / info_resolution_min
for ((reso, code_reso), axe_parasite) in zip(dico_resolutions.items(), [par_j, par_m, par_a]):
# vignette du haut, moyennes
df_reso_moy = ts.resample(code_reso).agg(['mean', 'count']) # une colonne moyenne, une colonne nombre de points dans la fenêtre
# définition d'un "masque" de booléens par une condition
if reso=="jour":
invalid = df_reso_moy['count'] <= nb_minutes_attendues_par_jour
elif reso=="mois":
invalid = df_reso_moy['count'] <= df_reso_moy.index.days_in_month * nb_minutes_attendues_par_jour
else:
code_couleur = 'orange'
invalid = df_reso_moy['count'] <= 365 * nb_minutes_attendues_par_jour
print(debut_rect, valeur, code_couleur)
# patch = patches.Rectangle(xy, w, h, linewidth=1, edgecolor=edgecolor, facecolor=facecolor)
if trace_rect_mensuels:
ax_cumul.add_patch(Rectangle((debut_rect, 0.1), -timedelta(days=30), valeur, color=code_couleur, alpha=0.8))
# restrict to the sum and null out invalid entries, using invalid as a mask
# https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
df_reso_moy.loc[invalid, 'mean'] = np.nan
ts_reso_moy = df_reso_moy['mean']
print(f"Rééchantillonnage par moyenne sur pas de temps {reso}, première date = {ts_reso_moy.index[0]}")
axe_parasite.plot(ts_reso_moy.index.shift(1, freq='D').to_pydatetime(), ts_reso_moy.to_numpy(), c=dico_resolutions_couleurs[reso],
marker='*', ls="None")
axe_parasite.step(df_reso_moy.index.shift(1, freq='D').to_pydatetime(), ts_reso_moy.to_numpy(), c=dico_resolutions_couleurs[reso],
label=reso) # , where='post')
# pause=input("fin des rectangles par mois ! ")
# vignette du bas, max
# TESTS : on enlève aussi le journalier - plot ou vlines ?
# ts_journalier.plot(color='red', ax=ax_cumul, label='cumul journalier')
ts_reso_max = ts.resample(code_reso).max()
ts_reso_max[invalid] = np.nan
print(f"Rééchantillonnage par max sur pas de temps {'jour'}, première date = {ts_reso_max[0]}")
ax_unique.plot(ts_reso_max.index.shift(1, freq='D').to_pydatetime(), ts_reso_max.to_numpy(), c=dico_resolutions_couleurs[reso],
marker='*', ls="None")
ax_unique.step(ts_reso_max.index.shift(1, freq='D').to_pydatetime(), ts_reso_max.to_numpy(), c=dico_resolutions_couleurs[reso])
# ax_cumul.plot(ts_journalier.index, ts_journalier, label=' pyplot',
# ls=':', color='yellow', lw=5, alpha=0.5)
ax_cumul.vlines(x=ts_journalier.index, ymin=0, ymax=ts_journalier, label="cumuls journaliers (vlines)",
color='red', lw=1, alpha=0.8)
ax_cumul.legend()
# max_valeur = max(df_lamedeau["lames d'eau en mm"].max(), df_mensuel["lames d'eau en mm"].max())
# min_valeur = min(0, df_lamedeau["lames d'eau en mm"].min(), df_mensuel["lames d'eau en mm"].min())
# ax1.set_ylim(min_valeur, df_mensuel["lames d'eau en mm"].max()*1.1)
# ax1.set_ylim(min_valeur, max_valeur * 1.1)
ax_5min.set_ylim(0, ts_lamedeau.max() * 1.1)
ax_cumul.set_ylim(0, ts_mensuel.max() * 1.1)
host_original.xaxis.set_major_locator(locator)
host_original.xaxis.set_major_formatter(formatter)
# jours : Memoruy Error avec vlines ?
"""
color_list = []
for debut_rect, valeur in zip(df_journalier.index, df_journalier["lames d'eau en mm"]):
if debut_rect.month in [12, 1, 2]:
code_couleur = 'blue'
elif debut_rect.month in [3, 4, 5]:
code_couleur = 'pink'
elif debut_rect.month in [6, 7, 8]:
code_couleur = 'yellow'
else:
code_couleur = 'orange'
fig.legend(loc='lower center', ncol=4)
color_list.append(code_couleur)
host_original.format_ydata = un_chiffre_apres_la_virgule
# colors avec un s car il y a une liste
ax2.vlines(df_journalier.index, 0, df_journalier["lames d'eau en mm"], colors=color_list)
"""
temps = datetime.now() - debut
plt.show()
print("temps écoulé Pandas avec mois en rectangles", temps)
# plt.clf()
def get_month_end(dt):
first_of_month = datetime(dt.year, dt.month, 1)
next_month_date = first_of_month + timedelta(days=32)
new_dt = datetime(next_month_date.year, next_month_date.month, 1)
return new_dt - timedelta(days=1)
def HautBas_trace_mensuel_avec_hlines(ts_lamedeau, ts_mensuel, ts_journalier=None, trace_hlines_mensuels=True):
debut = datetime.now()
def dernier_jour_du_mois(dt):
first_of_month = datetime(dt.year, dt.month, 1)
next_month_date = first_of_month + timedelta(days=32)
new_dt = datetime(next_month_date.year, next_month_date.month, 1)
return (new_dt - timedelta(days=1)).day
# moyennes par MOIS avec des rectangles
def trace_mensuel_avec_rectangles(ts_original, trace_journalier=False, trace_rect_mensuels=False):
"""
si DF
ax1 = df_lamedeau.loc[:, cols[1]].plot(label=cols[1],
title="Avec rectangles,5 min et cumuls mensuels (pas de temps fixe)",
color='purple', zorder=10)
test ici : Rectangles, axline et hlines
"""
# d'après cheatsheet pbpython
fig, (ax_cumul, ax_5min) = plt.subplots(nrows=2, ncols=1, sharex=True, figsize=(7, 4))
fig.suptitle("Lames d'eau à 5 min (bas) et cumuls journaliers et mensuels (haut)")
ax_cumul.set(ylabel="cumuls")
ax_5min.set(ylabel="lame d'eau \n à 5 min")
debut = datetime.now()
ts_lamedeau.plot(label="lames d'eau à 5 min", color='purple', zorder=10, ax=ax_5min)
plt.legend()
ts_mensuel= ts_original.resample("1M").sum()
ts_journalier = ts_original.resample("1D").sum()
# pas possible de mettre un 2e axe rien qu'avec des rectangles... DONC il faut mettre une ligne "guide" avec un plot
# moyenne_des_mois = ds_mensuel["lames d'eau en mm"].mean()
date_debut_pd = ts_lamedeau.index[0]
date_fin_pd = ts_lamedeau.index[-1]
fig, ax1 = plt.subplots(figsize=(7, 4))
fig.suptitle("chroniques_mois_rectangles")
ts_debutfin = pd.Series([ts_mensuel.mean(), ts_mensuel.mean()], index=[date_debut_pd, date_fin_pd])
ax1.plot(ts_original.index.to_pydatetime(), ts_original.to_numpy(), label="lames d'eau à 5 min",
color='purple', zorder=10)
ax1.set(ylabel="Lames d'eau à 5 min")
ts_debutfin.plot(ls=':', label='moyenne des cumuls mensuels', ax=ax_cumul)
(handles1, labels1) = plt.gca().get_legend_handles_labels()
# TESTS : on enlève les rectangles
couleurs = []
for debut_rect, valeur in zip(ts_mensuel.index, ts_mensuel):
if debut_rect.month in [12, 1, 2]:
code_couleur = 'blue'
elif debut_rect.month in [3, 4, 5]:
code_couleur = 'pink'
elif debut_rect.month in [6, 7, 8]:
code_couleur = 'yellow'
else:
code_couleur = 'orange'
couleurs.append(code_couleur)
# patch = patches.Rectangle(xy, w, h, linewidth=1, edgecolor=edgecolor, facecolor=facecolor)
# pas possible de mettre un 2e axe rien qu'avec des rectangles... DONC il faut mettre une ligne "guide" avec un plot
ax2 = ax1.twinx()
ax2.axhline(ts_mensuel.mean(), color="red", linestyle="--", label="moyenne des moyennes mensuelles")
ax2.set(ylabel="cumuls sur la durée (1 j ou 1 mois)")
if trace_rect_mensuels:
print("tracé des cumuls mensuels par des rectangles")
for date_debut_rect, valeur in zip(ts_mensuel.index.to_pydatetime(), ts_mensuel):
if date_debut_rect.month in [12, 1, 2]:
code_couleur = 'blue'
elif date_debut_rect.month in [3, 4, 5]:
code_couleur = 'pink'
elif date_debut_rect.month in [6, 7, 8]:
code_couleur = 'yellow'
else:
code_couleur = 'orange'
nb_jours_du_mois = dernier_jour_du_mois(date_debut_rect)
print(date_debut_rect, valeur, code_couleur, nb_jours_du_mois)
# patch = patches.Rectangle(xy, w, h, linewidth=1, edgecolor=edgecolor, facecolor=facecolor)
ax2.add_patch(Rectangle((date_debut_rect+timedelta(days=1), 0.1), -timedelta(days=nb_jours_du_mois), valeur, color=code_couleur, alpha=0.8))
if trace_journalier:
print("tracé des cumuls journaliers par des verticales")
ax2.vlines(x=ts_journalier.index.to_pydatetime(), ymin=0, ymax=ts_journalier.to_numpy(), color="blue", linestyle="--", label="moyennes journalières")
trace_hlines = False
if trace_hlines:
print("tracé des cumuls mensuels par des segments horizontaux")
ax2.hlines(y=ts_mensuel, xmax=ts_mensuel.index,
xmin=[date - timedelta(days=30) for date in ts_mensuel.index.to_pydatetime()],
label="cumuls mensuels", lw=3, alpha=0.8) # color=codes_couleur,
# TESTS : on enlève aussi le journalier - plot ou vlines ?
# ts_journalier.plot(color='red', ax=ax_cumul, label='cumul journalier')
(handles2, labels2) = plt.gca().get_legend_handles_labels()
# ax_cumul.plot(ts_journalier.index, ts_journalier, label=' pyplot',
# ls=':', color='yellow', lw=5, alpha=0.5)
if trace_hlines_mensuels:
ax_cumul.hlines(y=ts_mensuel, xmax=ts_mensuel.index,
xmin=[date - timedelta(days=30) for date in ts_mensuel.index], label="cumuls mensuels (hlines)",
color=couleurs, lw=1, alpha=0.9)
ax_cumul.vlines(x=ts_journalier.index, ymin=0, ymax=ts_journalier, label="cumuls journaliers (vlines)",
color='red', lw=1, alpha=0.8)
# Legende commune
plt.gca().legend(handles1+handles2, labels1+labels2)
ax_cumul.legend()
#fig.legend(loc=7)
# max_valeur = max(df_lamedeau["lames d'eau en mm"].max(), df_mensuel["lames d'eau en mm"].max())
# min_valeur = min(0, df_lamedeau["lames d'eau en mm"].min(), df_mensuel["lames d'eau en mm"].min())
# ax1.set_ylim(min_valeur, df_mensuel["lames d'eau en mm"].max()*1.1)
# ax1.set_ylim(min_valeur, max_valeur * 1.1)
ax1.set_ylim(0, ts_original.max() * 1.1)
ax2.set_ylim(0, max(ts_mensuel.max(), ts_journalier.max()) * 1.1)
ax_5min.set_ylim(0, ts_lamedeau.max() * 1.1)
ax_cumul.set_ylim(0, ts_mensuel.max() * 1.1)
# jours : Memory Error avec vlines ?
temps = datetime.now() - debut
plt.show()
print("temps écoulé Pandas avec mois en hlines", temps)
print("temps écoulé Pandas avec mois en rectangles", temps)
# plt.close(fig)
# todo : HautBas_trace_mensuel_avec_hlines_2y_en_haut
def HautBas_trace_mensuel_avec_hlines_2y_en_haut(ts_lamedeau, ts_mensuel, ts_journalier=None,
trace_hlines_mensuels=True):
debut = datetime.now()
def HautBas_trace_mensuel_avec_rectangles(ts_original, agg_par_cumul=True):
"""
si DF
ax1 = df_lamedeau.loc[:, cols[1]].plot(label=cols[1],
title="Avec rectangles,5 min et cumuls mensuels (pas de temps fixe)",
color='purple', zorder=10)
Avec des imperfections à corriger :
* étiquettes de dates : ajouter ConciseDateFormatter
* étiquettes des axes des y
"""
# https://stackoverflow.com/questions/22511550/gridspec-with-shared-axes-in-python
# fig, (ax_cumul, ax_5min) = plt.subplots(nrows=3, ncols=1, sharex=True, figsize=(7,4), gridspec_kw={'height_ratios': [5,5, 1]})
fig, (ax_cumul, ax_5min) = plt.subplots(nrows=2, ncols=1, sharex=True, figsize=(8, 5))
# tight_layout docs: [left, bottom, right, top] in normalized (0, 1) figure coordinates
# You can increase the space between suptitle and axes even more by lowering the rightest value:
fig.set_tight_layout({'rect': [0, .15, 1, 0.9], 'pad': 1.5, 'h_pad': 1.5})
# fig.subplots_adjust(bottom=0.9)
fig.suptitle("Lames d'eau à 5 min (bas) et cumuls journaliers et mensuels (haut)")
ax_cumul.set(ylabel="cumuls mensuels)")
ax_5min.set(ylabel="lame d'eau \n à 5 min")
ts_lamedeau.plot(label="lames d'eau à 5 min", color='purple', zorder=10, ax=ax_5min)
# plt.legend()
debut = datetime.now()
if agg_par_cumul:
ts_mensuel= ts_original.resample("1M").sum()
ts_journalier = ts_original.resample("1D").sum()
else:
ts_mensuel = ts_original.resample("1M").mean()
ts_journalier = ts_original.resample("1D").mean()
# pas possible de mettre un 2e axe rien qu'avec des rectangles... DONC il faut mettre une ligne "guide" avec un plot
# moyenne_des_mois = ds_mensuel["lames d'eau en mm"].mean()
date_debut_pd = ts_lamedeau.index[0]
date_fin_pd = ts_lamedeau.index[-1]
# d'après cheatsheet pbpython
fig, (ax_agg, ax_original) = plt.subplots(nrows=2, ncols=1, sharex=True, figsize=(7, 4))
if agg_par_cumul:
fig.suptitle("Lames d'eau à 5 min (bas) et cumuls journaliers et mensuels (haut)")
ax_agg.set(ylabel="cumuls")
ax_original.set(ylabel="lame d'eau \n à 5 min")
etiquette="lames d'eau à 5 min"
else:
fig.suptitle("Débit (bas) et débits moyens journaliers et mensuels (haut)")
ax_agg.set(ylabel="moyennes")
ax_original.set(ylabel="débit")
etiquette = "débit"
ts_debutfin = pd.Series([ts_mensuel.mean(), ts_mensuel.mean()], index=[date_debut_pd, date_fin_pd])
ax_original.plot(ts_original.index.to_pydatetime(), ts_original.to_numpy(), label=etiquette,
color='purple', zorder=10)
plt.legend()
ts_debutfin.plot(ls=':', label='moyenne des cumuls mensuels', ax=ax_cumul)
ax_agg.axhline(ts_mensuel.mean(), color="red", linestyle="--", label="moyenne des moyennes mensuelles")
# TESTS : on enlève les rectangles
couleurs = []
for debut_rect, valeur in zip(ts_mensuel.index, ts_mensuel):
if debut_rect.month in [12, 1, 2]:
for date_debut_rect, valeur in zip(ts_mensuel.index, ts_mensuel):
if date_debut_rect.month in [12, 1, 2]:
code_couleur = 'blue'
elif debut_rect.month in [3, 4, 5]:
elif date_debut_rect.month in [3, 4, 5]:
code_couleur = 'pink'
elif debut_rect.month in [6, 7, 8]:
elif date_debut_rect.month in [6, 7, 8]:
code_couleur = 'yellow'
else:
code_couleur = 'orange'
couleurs.append(code_couleur)
# patch = patches.Rectangle(xy, w, h, linewidth=1, edgecolor=edgecolor, facecolor=facecolor)
# TESTS : on enlève aussi le journalier - plot ou vlines ?
# ts_journalier.plot(color='red', ax=ax_cumul, label='cumul journalier')
# ax_cumul.plot(ts_journalier.index, ts_journalier, label=' pyplot',
# ls=':', color='yellow', lw=5, alpha=0.5)
if trace_hlines_mensuels:
ax_cumul.hlines(y=ts_mensuel, xmax=ts_mensuel.index,
xmin=[date - timedelta(days=30) for date in ts_mensuel.index], label="cumuls mensuels (hlines)",
color=couleurs, lw=1, alpha=0.9)
ax_cumul.set_ylim(0, ts_mensuel.max() * 1.1)
ax_cumul_j = ax_cumul.twinx()
ax_cumul_j.set(ylabel=("cumuls journaliers"))
ts_debutfin_j = pd.Series([ts_journalier.mean(), ts_journalier.mean()], index=[date_debut_pd, date_fin_pd])
ts_debutfin.plot(ls=':', label='moyenne des cumuls journaliers', ax=ax_cumul_j, color='orange')
ax_cumul_j.vlines(x=ts_journalier.index, ymin=0, ymax=ts_journalier, label="cumuls journaliers (vlines)",
color='red', lw=1, alpha=0.8)
# ax_cumul.legend()
# max_valeur = max(df_lamedeau["lames d'eau en mm"].max(), df_mensuel["lames d'eau en mm"].max())
# min_valeur = min(0, df_lamedeau["lames d'eau en mm"].min(), df_mensuel["lames d'eau en mm"].min())
# ax1.set_ylim(min_valeur, df_mensuel["lames d'eau en mm"].max()*1.1)
# ax1.set_ylim(min_valeur, max_valeur * 1.1)
ax_5min.set_ylim(0, ts_lamedeau.max() * 1.1)
ax_cumul.set_ylim(0, ts_mensuel.max() * 1.1)
# légende de figure
fig.legend(loc='lower center', mode="expand", borderaxespad=0, ncol=2)
temps = datetime.now() - debut
plt.show()
print("temps écoulé Pandas avec mois en hlines, 2 aces des y en haut", temps)
def trace_bars_hack_rectangles(ts_lamedeau, ts_mensuel, ts_journalier, hack_rect_mensuels=False):
debut = datetime.now()
nb_jours_du_mois = dernier_jour_du_mois(date_debut_rect)
print(date_debut_rect, valeur, code_couleur)
ax_agg.add_patch(Rectangle((date_debut_rect+timedelta(days=1), 0.1), -timedelta(days=nb_jours_du_mois), valeur, color=code_couleur, alpha=0.8))
"""
si DF
ax1 = df_lamedeau.loc[:, cols[1]].plot(label=cols[1],
title="Avec rectangles,5 min et cumuls mensuels (pas de temps fixe)",
color='purple', zorder=10)
"""
ax1 = ts_lamedeau.plot(label="lames d'eau à 5 min",
title="Avec collection de rectangles,5 min et cumuls mensuels (pas de temps fixe)",
color='purple', zorder=10)
# pas possible de mettre un 2e axe rien qu'avec des rectangles... DONC il faut mettre une ligne "guide" avec un plot
ax2 = ax1.twinx()
# moyenne_des_mois = ds_mensuel["lames d'eau en mm"].mean()
date_debut_pd = ts_lamedeau.index[0]
date_fin_pd = ts_lamedeau.index[-1]
ts_debutfin = pd.Series([ts_mensuel.mean(), ts_mensuel.mean()], index=[date_debut_pd, date_fin_pd])
ts_debutfin.plot(ls=':', ax=ax2)
ax_j = ax_agg.twinx()
ax_j.vlines(x=ts_journalier.index, ymin=0, ymax=ts_journalier, label="cumuls journaliers (vlines)",
color='red', lw=1, alpha=0.8)
# on prépare les rectangles
liste_rectangles = []
for debut_rect, valeur in zip(ts_mensuel.index, ts_mensuel):
if debut_rect.month in [12, 1, 2]:
code_couleur = 'blue'
elif debut_rect.month in [3, 4, 5]:
code_couleur = 'pink'
elif debut_rect.month in [6, 7, 8]:
code_couleur = 'yellow'
else:
code_couleur = 'orange'
if hack_rect_mensuels:
ax2.add_patch(Rectangle((debut_rect, 0.1), timedelta(days=30), valeur, color=code_couleur))
# print(debut_rect, valeur, code_couleur)
# alternative avec liste_rectangles.append puis ax2.add_collection
# descriptif : patch = patches.Rectangle(xy, w, h, linewidth=1, edgecolor=edgecolor, facecolor=facecolor)
# if hack_rect_mensuels:
# liste_rectangles.append(Rectangle((debut_rect, 0.1), timedelta(days=30), valeur, color=code_couleur))
# avec PatchCollection (pb avec dates ??)
# notre_cmap = ListedColormap(color_list)
# patches_collection = PatchCollection(liste_rectangles, match_original=True, alpha=1)
# patches_collection.set_array(np.arange(len(liste_rectangles)))
# ax2.add_collection(patches_collection, zorder=5)
# ts_journalier.plot(color='red')
# ts_journalier.plot(label=' cumul journalier, pd',
# ls=':', color='yellow', lw=2, alpha=0.5, ax=ax2)
ax2.vlines(x=ts_journalier.index, ymin=0, ymax=ts_journalier, label="cumuls journaliers (vlines)",
color='orange', lw=5, alpha=0.8)
fig.legend()
# max_valeur = max(df_lamedeau["lames d'eau en mm"].max(), df_mensuel["lames d'eau en mm"].max())
# min_valeur = min(0, df_lamedeau["lames d'eau en mm"].min(), df_mensuel["lames d'eau en mm"].min())
# ax1.set_ylim(min_valeur, df_mensuel["lames d'eau en mm"].max()*1.1)
# ax1.set_ylim(min_valeur, max_valeur * 1.1)
ax1.set_ylim(0, ts_lamedeau.max() * 1.1)
ax2.set_ylim(0, ts_mensuel.max() * 1.1)
plt.legend()
# jours : Memoruy Error avec vlines ?
"""
color_list = []
for debut_rect, valeur in zip(df_journalier.index, df_journalier["lames d'eau en mm"]):
if debut_rect.month in [12, 1, 2]:
code_couleur = 'blue'
elif debut_rect.month in [3, 4, 5]:
code_couleur = 'pink'
elif debut_rect.month in [6, 7, 8]:
code_couleur = 'yellow'
else:
code_couleur = 'orange'
ax_original.set_ylim(0, ts_original.max() * 1.1)
ax_agg.set_ylim(0, ts_mensuel.max() * 1.1)
ax_j.set_ylim(0, ts_journalier.max() * 1.1)
color_list.append(code_couleur)
# colors avec un s car il y a une liste
ax2.vlines(df_journalier.index, 0, df_journalier["lames d'eau en mm"], colors=color_list)
"""
temps = datetime.now() - debut
plt.show()
print("temps écoulé Pandas avec mois en rectangles 'patch collection' :", temps)
return temps
print("temps écoulé Pandas avec mois en rectangles", temps)
# plt.clf()
if __name__ == '__main__':
......@@ -1013,257 +1051,32 @@ if __name__ == '__main__':
print("chemin ", chemin_complet, " non valide")
# Deuxième atelier, figure avec plusieurs courbes, 2e axe des y
deuxieme_atelier = True
chemin_complet = askopenfilename()
# donnees_TD_ETP_csv(chemin_complet)
donnees_TD_ETP_2subplots(chemin_complet)
"""
# données TD4 ENTPE
# nom_fichier_TD4 = "D:/2020-TraitementChroniques/TestsVisuChroniques/donnees/ChroniquesPluieT.csv"
nom_fichier_TD4 = "D:/2020-TraitementChroniques/TestsVisuChroniques/donnees/donnees.csv"
nom_rep = "D:/2020-TraitementChroniques/TestsVisuChroniques/donnees"
print("Le chemin existe ? ... ", Path.is_dir(Path(nom_rep)))
tracer_td4 = False
if Path.is_file(Path(nom_fichier_TD4)) and tracer_td4:
print(f"traitement du fichier date, P, T : {nom_fichier_TD4} ")
# DF_ETP = donnees_TD_ETP_besogneux(nom_fichier_TD4)
# DF_ETP = donnees_TD_ETP_elegant(nom_fichier_TD4)
DF_ETP = donnees_TD_ETP_2subplots(nom_fichier_TD4)
print(DF_ETP.head(10))
print("phase suivante, fichier binaire de lames d'eau radar")
tracer_binaire = True
# recherche du nom du fichier binaire
if Path.is_file(Path(nom_fichier_binaire)) and tracer_binaire:
print(f"nom_chemin_binaire1 : {nom_fichier_binaire} ")
# vérification des dates
# lecture des valeurs
# cf fonctions Chronique.lire_chronique Lecture_Patnthere...chronique
uint16_valeurs = None
with open(nom_fichier_binaire, 'rb') as fic_binaire:
try:
uint16_valeurs = np.fromfile(fic_binaire, dtype=np.uint16, count=int(len(liste_dates)))
statut_lecture = "OK"
except:
statut_lecture = "erreur"
# VERIF
print("Ensemble des valeurs lues avant traitement (lacunes, diviseur...) : ", set(uint16_valeurs))
if statut_lecture == "OK":
# Traitement des lacunes
nb_lacunes = 0
for valeur in uint16_valeurs:
if int(valeur) == int(CODE_LACUNE_BINAIRE):
nb_lacunes += 1
print("Nombre de lacunes = ", nb_lacunes)
# on travaille avec des LAMES D'EAU en centième de mm, à passer en mm
valeurs = np.array(
[entier / DIVISEUR if entier != int(CODE_LACUNE_BINAIRE) else np.nan for entier in
uint16_valeurs])
# tracé
# PlotLy
debut = datetime.now()
if trace_plt:
trace_avec_plt(liste_dates, valeurs)
# trace_avec_plt(liste_dates, valeurs, "stem")
# trace_avec_plt(liste_dates, valeurs, "hlines")
# Pandas, dont DataShader
# préparation d'un DataFrame avec les données
if trace_ds or trace_bok or trace_pd:
# toute la liste ou juste DEBUT FIN
# liste_date_pd = pd.DatetimeIndex(liste_dates, freq='infer')
date_debut_pd = pd.to_datetime(date_premiere_valeur)
date_fin_pd = pd.to_datetime(date_premiere_valeur + (len_of_tvect - 1) * timedelta(minutes=PDT_OBS_EN_MIN))
print("dates de début et fin", date_debut_pd, date_fin_pd)
range_dates_pd_pour_index = pd.date_range(date_debut_pd, date_fin_pd, freq='5min')
print(len(range_dates_pd_pour_index), len(valeurs), len_of_tvect)
# les données doivent être dans un format DataFrame
# ts_lamedeau = pd.Series(valeurs, index=liste_date_pd)
ts_lamedeau = pd.Series(valeurs, index=range_dates_pd_pour_index)
print(ts_lamedeau.head(10))
print("Verification de l'analyse des dates : ", date_debut_pd, " mois ", date_debut_pd.month)
if trace_pd:
# POUR DATAFRAMES
# cols = list(df_lamedeau)
# print(cols)
tracer_DF_lamedeau_moyennes_mobiles(pd.DataFrame(ts_lamedeau))
# Deux courbes
debut = datetime.now()
ax1 = df_lamedeau.loc[:,cols[1]].plot (label=cols[1], title ="Avec pandas, 2 courbes", color='purple')
ax2 = ax1.twinx()
df_lamedeau.loc[:, cols[2]].plot(label=cols[1])
plt.show()
temps = datetime.now() - debut
print ("temps écoulé, Pandas 2 courbes (sans création DF):", temps)
# Une seule courbe
debut = datetime.now()
df_lamedeau.loc[:, cols[1]].plot(label=cols[1], title="Avec pandas", color='purple')
temps = datetime.now() - debut
plt.show()
print("temps écoulé Pandas (sans création DF):", temps)
# MOYENNES PDT FIXE
# Resample
# https: // towardsdatascience.com / playing - with-time - series - data - in -python - 959e2485bff8
print("Cumuls; pdt fixes")
# ax1 = df_lamedeau.loc[:, cols[1]].plot(label=cols[1],
# title="Avec pandas, données moyennées (pas de temps fixe)",
# color='purple')
ts_mensuel = ts_lamedeau.resample('M').sum()
ts_journalier = ts_lamedeau.resample('D').sum()
print("trace_3_courbes_avec_pandas(ts_lamedeau, ts_mensuel, ts_journalier)")
trace_3_courbes_avec_pandas(ts_lamedeau, ts_mensuel, ts_journalier)
print("trace_3_courbes_avec_pandas_donc_vlines(ts_lamedeau, ts_mensuel, ts_journalier)")
trace_3_courbes_avec_pandas_donc_vlines(ts_lamedeau, ts_mensuel, ts_journalier)
# barplots : une catastrophe
#ax1 = df_lamedeau.loc[:, cols[1]].plot(label=cols[1],
# title="Avec pandas données moyennées (pas de temps fixe)",
# color='purple')
#ax2 = ax1.twinx()
ax = df_mensuel.loc[:, cols[1]].plot(label=cols[1] + ' cumul mensuel', color='blue', kind='bar')
df_journalier.loc[:, cols[1]].plot(label=cols[1] + ' cumul journalier', color='orange', kind='bar')
# https: // stackoverflow.com / questions / 5902371 / matplotlib - bar - chart - with-dates
# ax.xaxis_date()
plt.legend()
plt.show()
# ===============================================================
# plot_moyenne_mois_avec_rectangles
# trace_mensuel_avec_rectangles marche
print(
" on passe trace_mensuel_avec_rectangles(ts_lamedeau,ts_mensuel,ts_journalier,trace_rect_mensuels=True)")
if False:
trace_mensuel_avec_rectangles(ts_lamedeau, ts_mensuel, ts_journalier, trace_rect_mensuels=True)
print("trace_mensuel_avec_hlines(ts_lamedeau, ts_mensuel, ts_journalier, trace_hlines=True)")
trace_mensuel_avec_hlines(ts_lamedeau, ts_mensuel, ts_journalier, trace_hlines=True)
print(
"HautBas_trace_mensuel_avec_rectangles(ts_lamedeau, ts_mensuel, ts_journalier, trace_rect_mensuels=True)")
HautBas_trace_mensuel_avec_rectangles(ts_lamedeau, ts_mensuel, ts_journalier, trace_rect_mensuels=True)
print(
"HautBas_trace_mensuel_avec_hlines(ts_lamedeau, ts_mensuel, ts_journalier, trace_hlines_mensuels=True)")
HautBas_trace_mensuel_avec_hlines(ts_lamedeau, ts_mensuel, ts_journalier, trace_hlines_mensuels=True)
# ===============================================================
# Marche pô, MemoryError même pour les mois ?...
print("et le dernier qui ne marche pas, pb avec collections et ax.add_collection avec un x en dates")
trace_bars_hack_rectangles(ts_lamedeau, ts_mensuel, ts_journalier, hack_rect_mensuels=True)
# pause = input("on continue vers les jours ?")
# jours : memory error ?
trace_rect_m = False
debut = datetime.now()
ax1 = ts_lamedeau.plot(label="lames d'eau à 5 min",
title="Avec rectangles corps du programme, moyennes journalières (pas de temps fixe)",
color='purple', zorder=10)
ax2 = ax1.twinx()
date_debut_pd = ts_lamedeau.index[0]
date_fin_pd = ts_lamedeau.index[-1]
ts_debutfin = pd.Series([ts_mensuel.mean(), ts_mensuel.mean()], index=[date_debut_pd, date_fin_pd])
ts_debutfin.plot(ls=':', ax=ax2)
# https://stackoverflow.com/questions/10550477/how-do-i-set-color-to-rectangle-in-matplotlib
color_list = []
#patch_list = []
for debut_rect, valeur in zip(ts_journalier.index, ts_journalier):
if debut_rect.month in [12,1,2]:
code_couleur = 'blue'
elif debut_rect.month in [3,4,5]:
code_couleur = 'pink'
elif debut_rect.month in [6,7,8]:
code_couleur = 'yellow'
else:
code_couleur = 'orange'
#color_list.append(code_couleur)
if trace_rect_m :
ax2.add_patch(Rectangle((debut_rect, 0.1), timedelta(days=30), valeur, color=code_couleur, alpha=0.8))
# print(debut_rect, valeur, code_couleur)
# patch = patches.Rectangle(xy, w, h, linewidth=1, edgecolor=edgecolor, facecolor=facecolor)
#patch_list.append(Rectangle((debut_rect, 0.1), timedelta(days=30), valeur))
#dates = [pd.to_datetime(datepd) for datepd in df_journalier.index]
# tests différentes solutions
#ax2.vlines(df_journalier.index, 0, df_journalier["lames d'eau en mm"],color=color_list)
#ax2.stem(df_journalier.index, df_journalier["lames d'eau en mm"])
notre_cmap = ListedColormap(color_list)
patches_collection = PatchCollection(patch_list, cmap=notre_cmap, alpha=1 )
patches_collection.set_array(np.arange(len(patch_list)))
ax1.add_collection(patches_collection, zorder=5)
max_valeur = max(ts_lamedeau.max(), ts_journalier.max())
min_valeur = min(0, ts_lamedeau.min(), ts_journalier.min())
ax1.set_ylim(0, ts_lamedeau.max() * 1.1)
ax2.set_ylim(0, ts_mensuel.max() * 1.1)
temps = datetime.now() - debut
plt.show()
print("temps écoulé Pandas, jours, avec vlines", temps)
# MOYENNES MOBILES
# Roll
# DataShader + bokeh, interactif
if trace_bok:
print("DataShader interactif ? ")
# def create_image_une_serie(df, x_range, y_range, w=900, h=300, col_x="pdt", col_y="lames d'eau en mm", how='linear')
p = base_plot(t_bokeh, y_range)
print(t_bokeh, x_range, y_range)
# # InteractiveImage rend p interactive en établissant un LIEN entre l'objet figure p et le callback défini
InteractiveImage(p, create_image_une_serie)
deuxieme_atelier = False
if deuxieme_atelier:
chemin_complet = askopenfilename()
# donnees_TD_ETP_csv(chemin_complet)
print("Dans un premier temps, on s'en remet entièrement à pandas")
donnees_TD_ETP_csv_panda_seul(chemin_complet)
print("Fermez la fenêtre Tk ; on continue")
# on peut récupérer la DataFrame ou pas...
DF_PTQ = donnees_TD_ETP_2subplots(chemin_complet)
# mais par exemple on en a besoin pour cette variante
donnees_TD_ETP_2subplots_variante(DF_PTQ)
quatrieme_atelier = True
binaire_chemin_complet = askopenfilename()
if Path.is_file(Path(binaire_chemin_complet)):
# CHRONIQUES
# lire_lame_deau_radar_5min(binaire_chemin_complet) # trace la figure mais on ne récupère pas les objets retournés
dates, valeurs = lire_lame_deau_radar_5min(binaire_chemin_complet) # trace la figure et on récupère les objets retournés
# tracer_proprement_une_longue_serie(dates, valeurs, info_chroniques=" série temporelle") # donc on peut les utiliser
# tracer_une_longue_serie_en3_resolutions_mieux(dates, valeurs, info_chroniques=" lame d'eau radar à 5 min")
tracer_une_longue_serie_lame_deau_en3_resolutions_verifs(dates, valeurs, info_chroniques=" lame d'eau radar à 5 min")
#trace_mensuel_avec_rectangles(pd.Series(valeurs, index=dates), trace_journalier=True, trace_rect_mensuels=True)
#HautBas_trace_mensuel_avec_rectangles(pd.Series(valeurs, index=dates))
"""
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment