3 votes

Tracer l'axe des timedeltas formaté en DD HH:MM:SS avec matplotlib

Je trace des données de vitesse/distance provenant d'événements de course, en utilisant Matplotlib, par exemple distance vs. temps, avec le temps en axe horizontal et la distance en axe vertical.

Mes entrées sont deux vecteurs, un contenant les valeurs de temps en "secondes depuis le début de l'événement", et l'autre contenant "la distance parcourue jusqu'à présent". Il peut y avoir de nombreux athlètes sur le même graphique, donc je peux les comparer.

Le problème est que si je trace uniquement le temps, j'obtiens un axe des X en nombre de secondes, ce qui n'est pas naturel à lire:

description de l'image

Je peux tracer les données en fonction de la date et de l'heure réelle, et j'obtiens des résultats lisibles, mais c'est en temps absolu, pas en temps écoulé depuis le début de l'événement (celui-ci a commencé vers 6h00 du matin):

description de l'image

Ce que je voudrais serait un moyen d'obtenir le temps écoulé au format HMS (comme dans le deuxième graphique, mais avec le temps relatif au début de l'événement), et éventuellement avec une "conscience" du niveau de zoom (passant d'heures:minutes, puis à jours:heures lorsque le niveau de zoom change, afin de ne pas encombrer les étiquettes avec des données non pertinentes par rapport à l'échelle).

Merci pour toute aide!

3voto

tcaswell Points 21489

Je soupçonne que le moyen le plus simple est d'écrire votre propre Formatter (doc) qui effectue la conversion en HSM.

import matplotlib

class myFormatter(matplotlib.ticker.Formatter):
    def __call__(self,in_value_in_seconds,pos=None):
        heures = int(in_value_in_seconds//(3600))
        in_value_in_seconds -= heures * 3600
        minutes = int(in_value_in_seconds//(60))
        in_value_in_seconds -= minutes * 60
        secondes = int(in_value_in_seconds)

        return str(heures) + ":" + str(minutes) + ":" + str(secondes)

C'est (je pense) le cas le plus simple et ne prend pas en charge le zoom. Il serait peut-être préférable d'intégrer une partie de cette logique dans un objet datetime.deltatime (ou de les prendre en tant qu'arguments).

Associé à MultipleLocator (doc), vous pouvez avoir un contrôle assez précis sur l'emplacement des graduations.

1voto

heltonbiker Points 4725

J'ai trouvé la solution suivante, c'est ce que j'utilise. Pas encore parfait (ne utilise pas des multiples de 60 comme ticks principaux), mais le format lui-même est ce que je veux:

def HMS(seconds, pos):
    seconds = int(seconds)
    hours = seconds / 3600
    seconds -= 3600 * hours
    minutes = seconds / 60
    seconds -= 60 * minutes
    if hours == 0:
        if minutes == 0:
            return "%ds" % (seconds)
        return "%dm%02ds" % (minutes, seconds)
    return "%dh%02dm" % (hours, minutes)

ax = plt.gca()
ax.xaxis.set_major_formatter(plt.FuncFormatter(HMS))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X