绘制python日期时间的累积图

ven*_*lin 16 python datetime graph matplotlib

假设我有一个日期时间列表,我们知道每个日期时间是事件发生的记录时间.

是否有可能在matplotlib中绘制此事件随时间发生的频率,在累积图中显示此数据(以便每个点大于或等于之前的所有点),而无需预处理此列表?(例如,将datetime对象直接传递给一些精彩的matplotlib函数)

或者我是否需要将此日期时间列表转换为字典项列表,例如:

{"year": 1998, "month": 12, "date": 15, "events": 92}
Run Code Online (Sandbox Code Playgroud)

然后从此列表生成图表?

Dav*_*d Z 11

这应该适合你:

counts = arange(0, len(list_of_dates))
plot(list_of_dates, counts)
Run Code Online (Sandbox Code Playgroud)

您当然可以为plot调用提供任何常用选项,以使图形看起来像您想要的那样.(我会指出matplotlib非常擅长处理日期和时间.)

另一种选择是hist函数 - 它有一个可能有用的选项'cumulative = True'.您可以创建一个累积直方图,显示截至任何给定日期发生的事件数量,如下所示:

from pyplot import hist
from matplotlib.dates import date2num
hist(date2num(list_of_dates), cumulative=True)
Run Code Online (Sandbox Code Playgroud)

但这会产生一个条形图,这可能不是你想要的,并且无论如何使水平轴上的日期标签正确显示可能需要一些捏造.

编辑:我感觉你真正想要的是每个日期的一个点(或条),相应的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)
Run Code Online (Sandbox Code Playgroud)

模块中的groupby函数itertools将生成您正在查找的数据类型:每个日期只有一个实例,并附datetime带有该日期的所有对象的列表(实际上是迭代器).正如Jouni在评论中所建议的那样,该step函数将给出一个图表,该图表在发生事件的每一天都会逐步升级,因此我建议使用它来代替plot.

(给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)
Run Code Online (Sandbox Code Playgroud)

我不认为它会对step函数产生的情节产生影响.


Eri*_*got 5

因此,您要从希望直方图的日期列表开始:

from datetime import  datetime
list_of_datetime_datetime_objects = [datetime(2010, 6, 14), datetime(1974, 2, 8), datetime(1974, 2, 8)]
Run Code Online (Sandbox Code Playgroud)

Matplotlib允许您将datetime.datetime对象转换为简单数字,正如David所说:

from matplotlib.dates import date2num, num2date
num_dates = [date2num(d) for d in list_of_datetime_datetime_objects]
Run Code Online (Sandbox Code Playgroud)

然后,您可以计算数据的直方图(查看NumPy histogram文档以获取更多选项(容器数量等)):

import numpy
histo = numpy.histogram(num_dates)
Run Code Online (Sandbox Code Playgroud)

由于您需要累积直方图,因此可以将各个计数添加到一起:

cumulative_histo_counts = histo[0].cumsum()
Run Code Online (Sandbox Code Playgroud)

直方图将需要bin大小:

from matplotlib import pyplot
Run Code Online (Sandbox Code Playgroud)

然后,您可以绘制累积直方图:

bin_size = histo[1][1]-histo[1][0]
pyplot.bar(histo[1][:-1], cumulative_histo_counts, width=bin_size)
Run Code Online (Sandbox Code Playgroud)

或者,您可能需要曲线而不是直方图:

# pyplot.plot(histo[1][1:], cumulative_histo_counts)
Run Code Online (Sandbox Code Playgroud)

如果您希望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
Run Code Online (Sandbox Code Playgroud)

在这里,gca()gcf()返回当前轴的身影,分别.

当然,您可以在strftime()上面的调用中调整显示日期的方式.

为了超越你的问题,我想提一下Matplotlib的画廊是一个非常好的信息来源:你通常可以通过找到看起来像你正在尝试做的图像来快速找到你需要的东西,并查看它们的来源码.

带有日期时间标签的累积曲线示例