使用 matplotlib 在刻度标签中创建包含日期和时间的图表

发布于 2024-10-28 18:07:00 字数 584 浏览 1 评论 0原文

我的数据位于以下结构的数组中,

[[1293606162197, 0, 0],
 [1293605477994, 63, 0],
 [1293605478057, 0, 0],
 [1293605478072, 2735, 1249],
 [1293606162213, 0, 0],
 [1293606162229, 0, 0]]

第一列是纪元时间(以 ms 为单位),第二列是 y1,第三列是 y2 >。我需要一个 x 轴为时间、左右 y 轴为 y1 和 y2 的绘图。

我一直在搜索文档,但找不到任何方法让我的 x 轴刻度显示日期和时间,例如“28/12 16:48”,即“日期/月份小时:分钟”。所有文档帮助我的只是单独显示日期,但这不是我想要的。

它实际上是我的上一个问题的后续问题。

I have my data in an array of the following structure,

[[1293606162197, 0, 0],
 [1293605477994, 63, 0],
 [1293605478057, 0, 0],
 [1293605478072, 2735, 1249],
 [1293606162213, 0, 0],
 [1293606162229, 0, 0]]

The first column is epoch time (in ms), second is y1 and third is y2. I need a plot with the time on the x-axis, and y1 and y2 on left and right y-axes.

I have been scouring through the documentation but couldn't find any way to get my x-axis ticks to display both date and time, like "28/12 16:48", i.e., "date/month hour:min". All the documentation helps me with is to display dates alone, but that is not what I want.

It is actually a follow-up to my previous question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

故人的歌 2024-11-04 18:07:00

我希望这有帮助。我一直很难理解 matplotlib 的日期。 Matplotlib 需要 浮点格式,即自纪元以来的天数。辅助函数 num2datedate2num 以及 python 内置 datetime 可用于相互转换。格式化业务是从示例中提取的。您可以使用 set_major_formatter 将任何绘图上的轴更改为日期轴。

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import dates
import datetime

a = np.array([
    [1293605162197, 0, 0],
    [1293605477994, 63, 0],
    [1293605478057, 0, 0],
    [1293605478072, 2735, 1249],
    [1293606162213, 0, 0],
    [1293606162229, 0, 0]])

d = a[:,0]
y1 = a[:,1]
y2 = a[:,2]

# convert epoch to matplotlib float format
s = d/1000
ms = d-1000*s  # not needed?
dts = map(datetime.datetime.fromtimestamp, s)
fds = dates.date2num(dts) # converted

# matplotlib date format object
hfmt = dates.DateFormatter('%m/%d %H:%M')

fig = plt.figure()
ax = fig.add_subplot(111)
ax.vlines(fds, y2, y1)

ax.xaxis.set_major_locator(dates.MinuteLocator())
ax.xaxis.set_major_formatter(hfmt)
ax.set_ylim(bottom = 0)
plt.xticks(rotation='vertical')
plt.subplots_adjust(bottom=.3)
plt.show()

结果

I hope this helps. I've always had a hard time with matplotlib's dates. Matplotlib requires a float format which is days since epoch. The helper functions num2date and date2num along with python builtin datetime can be used to convert to/from. The formatting business was lifted from this example. You can change an axis on any plot to a date axis using set_major_formatter.

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import dates
import datetime

a = np.array([
    [1293605162197, 0, 0],
    [1293605477994, 63, 0],
    [1293605478057, 0, 0],
    [1293605478072, 2735, 1249],
    [1293606162213, 0, 0],
    [1293606162229, 0, 0]])

d = a[:,0]
y1 = a[:,1]
y2 = a[:,2]

# convert epoch to matplotlib float format
s = d/1000
ms = d-1000*s  # not needed?
dts = map(datetime.datetime.fromtimestamp, s)
fds = dates.date2num(dts) # converted

# matplotlib date format object
hfmt = dates.DateFormatter('%m/%d %H:%M')

fig = plt.figure()
ax = fig.add_subplot(111)
ax.vlines(fds, y2, y1)

ax.xaxis.set_major_locator(dates.MinuteLocator())
ax.xaxis.set_major_formatter(hfmt)
ax.set_ylim(bottom = 0)
plt.xticks(rotation='vertical')
plt.subplots_adjust(bottom=.3)
plt.show()

result

蓝天白云 2024-11-04 18:07:00

在 matplotlib 的最新版本(例如 3.7.0)中,不需要显式地将日期转换为数字,matplotlib 在内部处理它。因此,只需将日期时间对象作为 x 值传递即可。

要显示自定义刻度,可以使用 DateFormatter 以及 MinuteLocator/MicrosecondLocator 等(取决于时间组件的分辨率)。

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime

data = [[1293606162197, 0, 0], [1293605477994, 63, 0], [1293605478057, 0, 0], 
        [1293605478072, 2735, 1249], [1293606162213, 0, 0], [1293606162229, 0, 0]]

# sort time-series by datetime
x, y1, y2 = zip(*sorted(data, key=lambda x: x[0]))

# convert to datetime objects
x = [datetime.datetime.fromtimestamp(i / 1000) for i in x]

fig, ax = plt.subplots()
ax.plot(x, y1, label='y1');       # plot y1 series
ax.plot(x, y2, label='y2')        # plot y2 series
ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m %H:%M'))  # format date/time
ax.xaxis.set_major_locator(mdates.MinuteLocator(interval=2))       # show every second minute
ax.legend()                                                        # show legend
fig.autofmt_xdate();                                               # format ticklabels

img

如果您不太关心日期时间如何显示为 x 刻度,则有 matplotlib.dates.ConciseDateFormatter 可以为您进行“漂亮”的格式化。对于手头的示例,它看起来像:

ax = plt.subplot()
ax.plot(x, y1, label='y1');       # plot y1 series
ax.plot(x, y2, label='y2')        # plot y2 series

locator = mdates.MinuteLocator(interval=2)
ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(locator))  # format date/time
ax.xaxis.set_major_locator(locator)                                 # show every second minute
ax.legend();

img2

In more recent versions of matplotlib (e.g. 3.7.0), there's no need to explicitly convert date to numbers, matplotlib handles it internally. So simply passing the datetime objects as x-values works.

To show custom ticks, DateFormatter along with MinuteLocator/MicrosecondLocator etc. (depending on the resolution of the time component) can be used.

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime

data = [[1293606162197, 0, 0], [1293605477994, 63, 0], [1293605478057, 0, 0], 
        [1293605478072, 2735, 1249], [1293606162213, 0, 0], [1293606162229, 0, 0]]

# sort time-series by datetime
x, y1, y2 = zip(*sorted(data, key=lambda x: x[0]))

# convert to datetime objects
x = [datetime.datetime.fromtimestamp(i / 1000) for i in x]

fig, ax = plt.subplots()
ax.plot(x, y1, label='y1');       # plot y1 series
ax.plot(x, y2, label='y2')        # plot y2 series
ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m %H:%M'))  # format date/time
ax.xaxis.set_major_locator(mdates.MinuteLocator(interval=2))       # show every second minute
ax.legend()                                                        # show legend
fig.autofmt_xdate();                                               # format ticklabels

img

If you don't particularly care how datetime is shown as x-ticks, there matplotlib.dates.ConciseDateFormatter that does "pretty" formatting for you. For the example at hand, that would look like:

ax = plt.subplot()
ax.plot(x, y1, label='y1');       # plot y1 series
ax.plot(x, y2, label='y2')        # plot y2 series

locator = mdates.MinuteLocator(interval=2)
ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(locator))  # format date/time
ax.xaxis.set_major_locator(locator)                                 # show every second minute
ax.legend();

img2

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文