绘制python日期时间的累积图

2024-05-01 22:06:06 发布

您现在位置:Python中文网/ 问答频道 /正文

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

在matplotlib中,是否可以在不预处理该列表的情况下,用图表表示该事件随时间发生的频率,并在累积图中显示该数据(使每个点大于或等于其之前的所有点)?(例如,将datetime对象直接传递给一些出色的matplotlib函数)

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

{"year": 1998, "month": 12, "date": 15, "events": 92}

然后从这个列表生成一个图表?


Tags: 数据对象函数列表datetime字典matplotlib时间
3条回答

所以,首先要列出要用直方图表示的日期列表:

from datetime import  datetime
list_of_datetime_datetime_objects = [datetime(2010, 6, 14), datetime(1974, 2, 8), datetime(1974, 2, 8)]

Matplotlib允许您将datetime.datetime对象转换为一个简单的数字,如David所述:

from matplotlib.dates import date2num, num2date
num_dates = [date2num(d) for d in list_of_datetime_datetime_objects]

然后可以计算数据的直方图(查看NumPy ^{} docs for more options (number of bins, etc.)):

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's gallery是一个非常好的信息来源:你通常可以快速找到你所需要的,只要找到像你想做的那样的图片,并查看它们的源代码。

Example of accumulative curve with datetime labels

我只是用高级软件工程的查特主任。很容易处理,尤其是约会。他们在python中也有很多例子。

这应该对你有用:

counts = arange(0, len(list_of_dates))
plot(list_of_dates, counts)

当然,您可以为plot调用提供任何常用选项,以使图看起来符合您的需要。(我将指出matplotlib非常擅长处理日期和时间。)

另一个选项是hist function-它有一个可能有用的“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)

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

(提醒我有关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函数生成的绘图有什么影响。

相关问题 更多 >