Tracer un graphique cumulatif des datetimes de python
Dire que j'ai une liste de datetimes, et nous savons que chaque datetime à la durée d'enregistrement d'un événement.
est-il possible dans matplotlib de représenter graphiquement la fréquence de cet événement se produisant dans le temps, en montrant ces données dans un graphique cumulatif (de sorte que chaque point est supérieur ou égal à tous les points qui l'ont précédé), sans prétraitement de cette liste? (e.g. passer des objets datetime directement à une fonction matplotlib merveilleuse)
Ou dois-je me tourner ce liste des datetimes dans une liste d'éléments dans le dictionnaire, tels que:
{"year": 1998, "month": 12, "date": 15, "events": 92}
puis de générer un graphique à partir de cette liste?
3 réponses
Cela devrait fonctionner pour vous:
counts = arange(0, len(list_of_dates))
plot(list_of_dates, counts)
vous pouvez bien sûr donner n'importe laquelle des options habituelles au plot
appeler pour que le graphique ressemble à ce que vous voulez. (Je ferai remarquer que matplotlib est très habile à traiter les dates et les heures.)
une Autre option serait le fonction hist - il y a une option 'cumulatif=vrai' qui pourrait être utile. Vous pouvez créer un histogramme cumulatif montrant le nombre d'événements qui se sont produits à une date donnée quelque chose comme ceci:
from pyplot import hist
from matplotlib.dates import date2num
hist(date2num(list_of_dates), cumulative=True)
mais cela produit un graphique à barres, qui pourrait ne pas être tout à fait ce que vous cherchez, et dans tous les cas, faire correctement les étiquettes de date sur l'affichage de l'axe horizontal exigera probablement un peu de doigté.
EDIT: j'ai l'impression que ce que vous voulez vraiment est un point (ou une barre) par date, avec la valeur y correspondante étant le nombre d'événements qui se sont produits jusqu'à (et y compris?) cette date. Dans ce cas, je serais suggère de faire quelque chose comme ceci:
grouped_dates = [[d, len(list(g))] for d,g in itertools.groupby(list_of_dates, lambda k: k.date())]
dates, counts = grouped_dates.transpose()
counts = counts.cumsum()
step(dates, counts)
groupby
de la fonction itertools
module de produire le type de données que vous recherchez: une seule instance de chaque date, accompagnée d'une liste (un itérateur, en fait) de tous les datetime
objets qui ont cette date. Comme suggéré par Jouni dans les commentaires, le step
fonction va donner un graphique qui s'élève à chaque jour où les événements se sont produits, donc je suggère d'utiliser cela à la place de plot
.
(Chapeau conseil à EOL pour me rappeler de cumsum
)
Si vous voulez avoir un point pour chaque jour, que des événements survenus ce jour-là ou non, vous aurez besoin de modifier le code ci-dessus un peu:
from matplotlib.dates import drange, num2date
date_dict = dict((d, len(list(g))) for d,g in itertools.groupby(list_of_dates, lambda k: k.date()))
dates = num2date(drange(min(list_of_dates).date(), max(list_of_dates).date() + timedelta(1), timedelta(1)))
counts = asarray([date_dict.get(d.date(), 0) for d in dates]).cumsum()
step(dates, counts)
Je ne pense pas que cela fera vraiment une différence pour l'intrigue produite par le step
la fonction si.
Donc, vous commencez avec une liste de dates que vous voulez histogramme:
from datetime import datetime
list_of_datetime_datetime_objects = [datetime(2010, 6, 14), datetime(1974, 2, 8), datetime(1974, 2, 8)]
Matplotlib vous permet de convertir un datetime.datetime
objet dans un simple nombre, comme David mentionné:
from matplotlib.dates import date2num, num2date
num_dates = [date2num(d) for d in list_of_datetime_datetime_objects]
ensuite, Vous pouvez calculer l'histogramme de vos données (regardez NumPy histogram
docs pour plus d'options (nombre de bacs, etc.)):
import numpy
histo = numpy.histogram(num_dates)
Puisque vous voulez le cumulatif histogramme, vous ajoutez des chefs ensemble:
cumulative_histo_counts = histo[0].cumsum()
L'histogramme de la parcelle devra le bin taille:
from matplotlib import pyplot
vous pouvez alors tracer l'histogramme cumulatif:
bin_size = histo[1][1]-histo[1][0]
pyplot.bar(histo[1][:-1], cumulative_histo_counts, width=bin_size)
alternativement, vous pourriez vouloir une courbe au lieu d'un histogramme:
# pyplot.plot(histo[1][1:], cumulative_histo_counts)
si vous voulez des dates sur l'axe des x au lieu des nombres, vous pouvez convertir les nombres en dates et demander à matplotlib d'utiliser des chaînes de dates comme tics, au lieu des nombres:
from matplotlib import ticker
# The format for the x axis is set to the chosen string, as defined from a numerical date:
pyplot.gca().xaxis.set_major_formatter(ticker.FuncFormatter(lambda numdate, _: num2date(numdate).strftime('%Y-%d-%m')))
# The formatting proper is done:
pyplot.gcf().autofmt_xdate()
# To show the result:
pyplot.show() # or draw(), if you don't want to block
Ici gca()
et gcf()
retourner l'axe et la figure actuels, respectivement.
bien sûr, vous pouvez adapter la façon dont vous l'affichage des dates, dans l'appel à strftime()
ci-dessus.
aller au-delà De votre question, je tiens à mentionner que Matplotlib galerie est une très bonne source d'information: vous pouvez généralement trouver rapidement ce dont vous avez besoin en trouvant simplement des images qui ressemblent à ce que vous essayez de faire, et en regardant leur source code.
je viens d'utiliser le directeur graphique de l'ingénierie logicielle avancée. Très facile à gérer, surtout avec les dates. Ils ont beaucoup d'exemples en python.