Скажите, что у меня есть список datetimes, и мы знаем, что каждая дата и время зарегистрированное время случая события.
Действительно ли возможно в matplotlib изобразить частоту в виде графика этого события, происходящего со временем, показывая эти данные в кумулятивном графике (так, чтобы каждая точка была больше или равной всем точкам, которые пошли перед ним), не предварительно обрабатывая этот список? (например, передающая дата и время возражает непосредственно против некоторой замечательной функции matplotlib),
Или сделайте я должен превратить этот список datetimes в список объектов словаря, таких как:
{"year": 1998, "month": 12, "date": 15, "events": 92}
и затем генерируйте график из этого списка?
Это должно сработать для вас:
counts = arange(0, len(list_of_dates))
plot(list_of_dates, counts)
Вы, конечно, можете дать любой из обычных параметров вызову plot
, чтобы график выглядел так, как вы хотите. (Я отмечу, что matplotlib очень хорошо разбирается в датах и времени.)
Другой вариант - функция hist - у нее есть опция «cumulative = True», которая может быть полезна. Вы можете создать кумулятивную гистограмму, показывающую количество событий, которые произошли на любую заданную дату, примерно так:
from pyplot import hist
from matplotlib.dates import date2num
hist(date2num(list_of_dates), cumulative=True)
Но это дает гистограмму, которая может быть не совсем той, что вы ищете, и в любом случае правильное отображение меток даты на горизонтальной оси, вероятно, потребует некоторой подделки.
РЕДАКТИРОВАТЬ : у меня возникает ощущение, что на самом деле вам нужна одна точка (или полоса) на дату, с соответствующим значением y, которое представляет собой количество событий, которые произошли до (включительно?) эта дата. В этом случае я бы посоветовал сделать что-то вроде этого:
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
из модуля itertools
выдаст именно те данные, которые вы ищете: только один экземпляр каждой даты, сопровождаемый списком (фактически итератором) всех объектов datetime
, имеющих эту дату. Как было предложено Джоуни в комментариях, функция step
даст график, который увеличивается каждый день, когда происходят события, поэтому я бы предложил использовать его вместо графика
.
(Совет EOL за напоминание о cumsum
)
Если вы хотите получать одно очко за каждый день, независимо от того, произошли ли в этот день какие-либо события или нет, вам понадобится чтобы немного изменить приведенный выше код:
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)
Я не думаю, что это действительно повлияет на график, созданный функцией step
.
Итак, вы начинаете со списка дат, которые хотите отобразить в гистограмме:
from datetime import datetime
list_of_datetime_datetime_objects = [datetime(2010, 6, 14), datetime(1974, 2, 8), datetime(1974, 2, 8)]
Matplotlib позволяет преобразовать объект datetime.datetime
в простой число, как упомянул Дэвид:
from matplotlib.dates import date2num, num2date
num_dates = [date2num(d) for d in list_of_datetime_datetime_objects]
Затем вы можете рассчитать гистограмму своих данных (посмотрите гистограмму NumPy гистограмму
, чтобы узнать о дополнительных параметрах (количество ячеек и т. д.) ):
import numpy
histo = numpy.histogram(num_dates)
Поскольку вам нужна кумулятивная гистограмма , вы складываете отдельные счетчики вместе:
cumulative_histo_counts = histo[0].cumsum()
Для построения гистограммы потребуется размер ячейки:
from matplotlib import pyplot
Затем вы можете построить кумулятивную гистограмму:
bin_size = histo[1][1]-histo[1][0]
pyplot.bar(histo[1][:-1], cumulative_histo_counts, width=bin_size)
В качестве альтернативы вы можете может потребоваться кривая вместо гистограммы:
# pyplot.plot(histo[1][1:], cumulative_histo_counts)
Если вам нужны даты на оси x вместо чисел, вы можете преобразовать числа обратно в даты и попросить matplotlib использовать строки даты в качестве отметок вместо чисел:
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
Здесь , gca ()
и gcf ()
возвращают текущую ось и фигуру соответственно.
Конечно, вы можете адаптировать способ отображения дат в вызове strftime ()
выше.
Чтобы выйти за рамки вашего вопроса, я хотел бы упомянуть, что Галерея Matplotlib - очень хороший источник информации: обычно вы можете быстро найти то, что вам нужно, просто найдя изображения, которые выглядят так, как вы пытаясь сделать, и глядя на их исходный код.
Я просто использую chart director из Advanced Software Engineering. С ним очень легко работать, особенно с датами. У них есть много примеров и на python.