[PYTHON] matplotlib Ecrire du texte dans un graphique de séries chronologiques

introduction

J'ai fait un graphique de série chronologique, mais je suis tombé sur la méthode d'affichage du texte à la position spécifiée, et je l'ai vérifié, donc je vais le télécharger. Notre environnement est le suivant. Le travail se fait sur le notebook Juputer.

Exemple

fig_test.png

Où j'ai conçu

Dans le graphique présenté dans l'exemple, la période manquante des données de débit est remplie en gris et la période est affichée sous forme de texte. L'affichage du texte de cette période manquante est le point culminant de cet article.

En ce qui concerne le réglage de l'axe du graphique de série chronologique, je suis l'article suivant que j'ai publié plus tôt.

https://qiita.com/damyarou/items/19f19658b618fd05b3b6

Comment afficher du texte sur un graphique de série chronologique

Créez une liste de chaînes de caractères montrant les points de début et de fin de la période manquante et convertissez-la en type datetime

    #début de l'absence de données de sortie (début de la période manquante)
    _sss=['2014-10-29',
          '2014-12-01',
          '2017-08-01',
          '2018-01-01',
          '2018-06-01',
          '2019-06-01']
    #fin d'absence de données de sortie
    _sse=['2014-10-31',
          '2014-12-31',
          '2017-12-31',
          '2018-04-30',
          '2018-08-31',
          '2019-12-31']
    sss=[]
    sse=[]
    for ss,se in zip(_sss,_sse):
        ss = datetime.datetime.strptime(ss, '%Y-%m-%d')
        se = datetime.datetime.strptime(se, '%Y-%m-%d')
        sss=sss+[ss]
        sse=sse+[se]

Tout en tournant la boucle pour chaque période manquante, remplissez les parties nécessaires de gris et affichez le texte

        for ss,se in zip(sss,sse):
            xx=dates.date2num(ss)+(dates.date2num(se)-dates.date2num(ss))/2 #Spécifiez la coordonnée centre x de la position d'affichage du texte
            x1=dates.date2num(xmin) #Le point de départ de la coordonnée x du graphique
            x2=dates.date2num(xmax) #Point de fin de coordonnée X du graphique
            if x1<xx<x2: #Dessin de texte si la position d'affichage du texte se situe entre les points de début et de fin du graphique
                plt.axvspan(ss,se,color='#cccccc')
                xs=dates.num2date(xx)
                ys=ymin+0.3*(ymax-ymin)
                tstr1 = ss.strftime('%Y/%m/%d')
                tstr2 = se.strftime('%Y/%m/%d')
                sstr=tstr1+'~'+tstr2+'\nno discharge data'        
                plt.text(xs,ys,sstr,ha='center',va='bottom',fontsize=fsz,rotation=90,linespacing=1.5)

Le remplissage en gris se fait avec ax vspan.

Pour spécifier la position d'affichage du texte, définissez import matplotlib.dates comme dates`` et `` `dates.date2num ()` `` (à partir de minuit + 1 le 1er janvier 1 AD) J'utilise les fonctions (convertir les jours en virgule flottante) et `` `` dates.num2date () '' (convertir la virgule flottante en `` datetime).

Dans le programme, des diagrammes similaires sont créés chaque année pendant plusieurs années, de sorte que le processus de "vérification des points de début et de fin de l'axe des x pour chaque graphique et dessin uniquement lorsque la position d'affichage du texte est entre les deux" Si vous ne le faites pas, le texte sera affiché dans un endroit ridicule, c'est ainsi que cela se fait.

Le texte est sorti avec un plt.text () '' sur deux lignes. Cet espacement des lignes est ajusté par `` linespacing = 1.5 ''`.

Voir ci-dessous pour les fonctions.

Je suis conscient mais je ne fais pas

Si vous regardez attentivement le graphique, vous pouvez voir qu'il y a un espace vide pour un jour avant et après la période manquante à la fin d'octobre et avant la période manquante en décembre. En effet, l'heure de la date indiquée par les données est minuit du jour, de sorte que la période de minuit à 24h00 du jour reste vide. Étant donné que les données du tracé sont des données quotidiennes, elles doivent être remplies avec bar, mais cela prend beaucoup de temps à dessiner, il est donc normal de remplir avec `` `` fill_between

Programme complet

# Time series drawing
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime
import matplotlib.dates as dates
import matplotlib.dates as mdates


def inp_rf():
    fnameR='xls_rdata_20190630.xlsx'
    df = pd.read_excel(fnameR,index_col=0)
    df.index = pd.to_datetime(df.index, format='%Y/%m/%d')
    df_rf=df['2013/01/01':'2019/12/31']
    return df_rf


def inp_qq():
    fnameR='df_qq1.csv'
    df = pd.read_csv(fnameR,index_col=0)
    df.index = pd.to_datetime(df.index, format='%Y/%m/%d')
    df_qq=df['2013/01/01':'2019/12/31']
    return df_qq

    
def drawfig(df_rf,df_qq):
    # start of no discharge data
    _sss=['2014-10-29',
          '2014-12-01',
          '2017-08-01',
          '2018-01-01',
          '2018-06-01',
          '2019-06-01']
    # end of no discharge data
    _sse=['2014-10-31',
          '2014-12-31',
          '2017-12-31',
          '2018-04-30',
          '2018-08-31',
          '2019-12-31']
    sss=[]
    sse=[]
    for ss,se in zip(_sss,_sse):
        ss = datetime.datetime.strptime(ss, '%Y-%m-%d')
        se = datetime.datetime.strptime(se, '%Y-%m-%d')
        sss=sss+[ss]
        sse=sse+[se]
    yyyy=np.array([2013,2014,2015,2016,2017,2018,2019])
    fsz=12
    st='01-01'
    ed='12-31'
    for year in yyyy:
        sxmin=str(year)+'-'+st
        sxmax=str(year)+'-'+ed
        plt.figure(figsize=(16,6),facecolor='w')
        plt.rcParams['font.size']=fsz
        xmin = datetime.datetime.strptime(sxmin, '%Y-%m-%d')
        xmax = datetime.datetime.strptime(sxmax, '%Y-%m-%d')
        ymin=0
        ymax=400
        plt.xlim([xmin,xmax])
        plt.ylim([ymin,ymax])
        sxlabel='Date ({0})'.format(year)
        plt.xlabel(sxlabel)
        plt.ylabel('Daily discharge Q (m$^3$/s)')
        plt.grid(which='major',axis='both',color='#999999',linestyle='--')
        for ss,se in zip(sss,sse):
            xx=dates.date2num(ss)+(dates.date2num(se)-dates.date2num(ss))/2
            x1=dates.date2num(xmin)
            x2=dates.date2num(xmax)
            if x1<xx<x2:
                plt.axvspan(ss,se,color='#cccccc')
                xs=dates.num2date(xx)
                ys=ymin+0.3*(ymax-ymin)
                tstr1 = ss.strftime('%Y/%m/%d')
                tstr2 = se.strftime('%Y/%m/%d')
                sstr=tstr1+'~'+tstr2+'\nno discharge data'        
                plt.text(xs,ys,sstr,ha='center',va='bottom',fontsize=fsz,rotation=90,linespacing=1.5)

        plt.fill_between(df_qq.index,df_qq['q_tot'],0,color='#ff00ff',label='Q (total)')
        plt.fill_between(df_qq.index,df_qq['q_lll']+df_qq['q_rrr'],0,color='#00ff00',label='Q (Right)')
        plt.fill_between(df_qq.index,df_qq['q_lll'],0,color='#ff0000',label='Q (Left)')
        plt.twinx()
        plt.ylim([ymax,ymin])
        plt.ylabel('Daily rainfall RF (mm/day)')
        plt.fill_between(df_rf.index,df_rf['RF'],0,color='#0000ff',label='RF in basin by JWA')
        plt.fill_between([0],[0],0,color='#ff00ff',label='Q (total)')
        plt.fill_between([0],[0],0,color='#00ff00',label='Q (Right)')
        plt.fill_between([0],[0],0,color='#ff0000',label='Q (Left)')
        plt.legend(bbox_to_anchor=(1, 1.01), loc='lower right', borderaxespad=0.1, ncol=4, shadow=True, fontsize=fsz-2)
    
        #plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%d-%b-%Y'))
        plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%d-%b'))
        plt.gca().xaxis.set_major_locator(mdates.MonthLocator(interval=1))
        plt.gca().xaxis.set_minor_locator(mdates.MonthLocator(interval=1))
        plt.gcf().autofmt_xdate()

        fnameF='fig_'+str(year)+'.png'
        plt.savefig(fnameF, dpi=100, bbox_inches="tight", pad_inches=0.1)
        plt.show()


def main():
    df_rf=inp_rf()
    df_qq=inp_qq()
    drawfig(df_rf,df_qq)
    

#==============
# Execution
#==============
if __name__ == '__main__': main()

c'est tout

Recommended Posts

matplotlib Ecrire du texte dans un graphique de séries chronologiques
Diagramme de séries chronologiques / Matplotlib
Graphique des données de séries chronologiques en Python à l'aide de pandas et matplotlib
[Dessin graphique] J'ai essayé d'écrire un graphique à barres multi-séries avec matplotlib et seaborn
Comment comparer des données de séries chronologiques - Dérivée DTW, DTW-
Comment dessiner un graphique avec Matplotlib
Comment gérer les données de séries chronologiques (mise en œuvre)
Comment éviter d'écrire% matplotlib en ligne à chaque fois
Décomposition des séries temporelles
Comment lire les données de séries chronologiques dans PyTorch
Album graphique matplotlib
[Python] Comment dessiner un graphique linéaire avec Matplotlib
Python: analyse des séries chronologiques
Dessin graphique avec matplotlib
J'ai lu 10 livres liés aux données de séries chronologiques, je vais donc rédiger une critique.
Question sur la série chronologique Python
Analyse des séries chronologiques RNN_LSTM1
Analyse des séries chronologiques 1 Principes de base
Graphique de bande avec matplotlib
Comment utiliser Matplotlib
Afficher les séries chronologiques TOPIX
J'ai créé un package pour filtrer les séries chronologiques avec python
Défi des prévisions de ventes futures: ② Analyse des séries chronologiques à l'aide de PyFlux
Une méthode d'étude pour les débutants pour apprendre l'analyse des séries chronologiques
Reformatez l'axe des temps du graphique de la série chronologique des pandas avec matplotlib
[Introduction à matplotlib] Lire l'heure de fin à partir des données COVID-19 ♬
Écrivez des graphiques en temps réel avec Matplotlib sur le notebook Jupyter
Défi des prévisions de ventes futures: ⑤ Analyse des séries chronologiques par Prophet