在 matplotlib 轴上格式化日期时间以获得小时和分钟的问题

Posted

技术标签:

【中文标题】在 matplotlib 轴上格式化日期时间以获得小时和分钟的问题【英文标题】:Problem formatting datetime on matplotlib axis to get just hour and minutes 【发布时间】:2021-11-10 02:11:04 【问题描述】:

这是我目前的简单情节:

正如我们所见,ax y 的格式非常糟糕。轴上的时间刻度仅以小时和分钟为单位变化,因此,我只想显示小时和分钟。

我正在尝试使用 mdates.DateFormatter 如下:

axs.yaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))

但它不起作用。结果是这样的:

我认为我使用了正确的标记 '%H:%M'

为什么它不起作用?

编辑:

这是一个可复制的小代码。 this post 上建议的解决方案相似但不一样。那里的问题与格式化日期有关,而不是时间。我的问题是让时间正确格式化为 HH:MM。

import pandas as pd
from pandas import Timestamp
import datetime


daux = pd.DataFrame('resolved_at': 3781: Timestamp('2021-06-04 12:18:00'), 504: Timestamp('2021-04-07 17:39:00'), 4720: Timestamp('2021-06-18 17:28:00'), 6310: Timestamp('2021-07-07 18:38:00'), 4016: Timestamp('2021-06-09 06:22:00'), 4575: Timestamp('2021-06-17 09:34:00'), 3071: Timestamp('2021-05-24 14:42:00'), 3753: Timestamp('2021-06-04 06:32:00'), 5999: Timestamp('2021-07-05 16:51:00'), 141: Timestamp('2021-03-23 21:02:00'), 3320: Timestamp('2021-05-27 10:25:00'), 4267: Timestamp('2021-06-12 16:49:00'), 5130: Timestamp('2021-06-25 07:14:00'), 273: Timestamp('2021-03-27 11:01:00'), 1696: Timestamp('2021-05-03 14:25:00'), 66: Timestamp('2021-03-19 12:59:00'), 4544: Timestamp('2021-06-16 20:32:00'), 5807: Timestamp('2021-07-03 08:18:00'), 1352: Timestamp('2021-04-28 09:55:00'), 5358: Timestamp('2021-06-29 10:14:00'), 3210: Timestamp('2021-05-26 08:42:00'), 2475: Timestamp('2021-05-14 16:41:00'), 5165: Timestamp('2021-06-25 10:23:00'), 715: Timestamp('2021-04-17 09:51:00'), 3227: Timestamp('2021-05-26 10:09:00'), 6085: Timestamp('2021-07-06 09:02:00'), 4009: Timestamp('2021-06-08 20:39:00'), 3541: Timestamp('2021-05-31 18:47:00'), 5788: Timestamp('2021-07-02 22:24:00'), 449: Timestamp('2021-04-06 08:57:00'), 4695: Timestamp('2021-06-18 13:57:00'), 836: Timestamp('2021-04-20 21:07:00'), 4876: Timestamp('2021-06-22 07:58:00'), 4206: Timestamp('2021-06-11 17:56:00'), 3505: Timestamp('2021-05-31 10:49:00'), 3306: Timestamp('2021-05-27 08:52:00'), 1595: Timestamp('2021-05-01 07:59:00'), 2611: Timestamp('2021-05-18 06:27:00'), 5776: Timestamp('2021-07-02 20:02:00'), 180: Timestamp('2021-03-25 05:31:00'), 3633: Timestamp('2021-06-02 08:43:00'), 4502: Timestamp('2021-06-16 12:56:00'), 2031: Timestamp('2021-05-07 10:21:00'), 5625: Timestamp('2021-07-01 17:57:00'), 2393: Timestamp('2021-05-13 06:45:00'), 5675: Timestamp('2021-07-02 08:27:00'), 6187: Timestamp('2021-07-06 21:39:00'), 5077: Timestamp('2021-06-24 12:32:00'), 4531: Timestamp('2021-06-16 17:41:00'), 6132: Timestamp('2021-07-06 14:11:00'),'n_pkgs': 3781: 1, 504: 1, 4720: 1, 6310: 1, 4016: 1, 4575: 2, 3071: 1, 3753: 1, 5999: 1, 141: 1, 3320: 1, 4267: 1, 5130: 1, 273: 1, 1696: 1, 66: 1, 4544: 1, 5807: 1, 1352: 1, 5358: 2, 3210: 1, 2475: 1, 5165: 1, 715: 1, 3227: 1, 6085: 1, 4009: 1, 3541: 2, 5788: 2, 449: 1, 4695: 1, 836: 1, 4876: 1, 4206: 1, 3505: 1, 3306: 1, 1595: 1, 2611: 1, 5776: 2, 180: 1, 3633: 1, 4502: 1, 2031: 1, 5625: 1, 2393: 4, 5675: 2, 6187: 1, 5077: 1, 4531: 1, 6132: 1,'dayofweek': 3781: 4, 504: 2, 4720: 4, 6310: 2, 4016: 2, 4575: 3, 3071: 0, 3753: 4, 5999: 0, 141: 1, 3320: 3, 4267: 5, 5130: 4, 273: 5, 1696: 0, 66: 4, 4544: 2, 5807: 5, 1352: 2, 5358: 1, 3210: 2, 2475: 4, 5165: 4, 715: 5, 3227: 2, 6085: 1, 4009: 1, 3541: 0, 5788: 4, 449: 1, 4695: 4, 836: 1, 4876: 1, 4206: 4, 3505: 0, 3306: 3, 1595: 5, 2611: 1, 5776: 4, 180: 3, 3633: 2, 4502: 2, 2031: 4, 5625: 3, 2393: 3, 5675: 4, 6187: 1, 5077: 3, 4531: 2, 6132: 1)



import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import seaborn as sns 

import matplotlib.dates as mdates




f, axs = plt.subplots(1, 1, figsize=(5,5),  sharex=True)


d = daux

d = d[['n_pkgs','dayofweek', 'resolved_at']].pivot('resolved_at', 'dayofweek', 'n_pkgs').fillna(0)
display(d)
g = sns.heatmap(d, ax=axs, cmap='binary')


axs.yaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))


有了这个代码片段,错误是 100% 可重现的。

感谢迄今为止的所有帮助。谢谢。

【问题讨论】:

感谢您的回复,特伦顿。我确信“resolved_at”是一个时间戳。我已经尝试过按照您提到的进行转换,但没有成功。我将添加一些代码以使其可复制。 刚试过,没用:/我正在使用 seaborn 热图进行绘图。会不会跟它有关系? @TrentonMcKinney,昨天我有点慌张,很抱歉没有包括所有需要的东西。我刚刚编辑了问题并添加了一段可重现的代码,以便您自己查看问题。建议的帖子相似,但不一样。他们正在尝试格式化日期,这里的问题是时间。它应该像使用正确的标签(%H:%M)一样简单,但存在问题。可能有一些非常明显的东西我在这里可能看不到。感谢您迄今为止的帮助。 如果有人可以,请再次打开问题,我认为它已经解决了。谢谢 嗨@TrentonMcKinney。是的,答案告诉这样做,但它根本没有解决问题。它确实根据需要绘制数字,但是由于您将其转换为字符串,因此它失去了比例意义并成为唯一的对象,因此,假设您在两个标记之间有很大的时间间隔,它不会以正确的方式显示在图表上比例。我刚刚运行了一个代码,删除了 12:00 到 16:00 之间的所有事件。 17:xx 的活动紧挨着 11:xx 的活动。所以是的,它显示了正确的文本,但有一个更大的问题:丢失了正确的时间比例。 【参考方案1】: 这似乎与answer 到Date axis in heatmap seaborn 大致相同 使用.pivot转换dataframe,然后用.strftime('%H:%M')转换列'H:M'格式 在seaborn.heatmap 中使用xticklabels=1yticklabels=1 来显示所有值。 刻度是 0 索引和离散的,而不是日期时间索引。显示的值只是标签。见p.get_xticklabels()
# pivot daux
dfp = daux.pivot(index='dayofweek', columns='resolved_at', values='n_pkgs')

# convert the columns to H:M
dfp.columns = dfp.columns.strftime('%H:%M')

# plot
fig = plt.figure(figsize=(12, 6))
p = sns.heatmap(dfp, xticklabels=1, yticklabels=1)

【讨论】:

它解决了标签,但是当您将时间对象转换为字符串对象时,它会丢失刻度的时间关系。我不能在这里通过图片,但如果你添加这一行。 daux = daux[(daux.resolved_at.dt.time datetime.time(16))] 它会删除 12:00 到 16:00 之间的所有事件。您会看到 11:xx 的事件在情节上以一个单位向前跳到 17:xx,失去了 4 小时的间隔。 @SergioPolimante 在热图索引上没有时间关系,刻度是 0 索引和离散的,而不是连续的日期时间索引。 情节的时间尺度与情节的种类无关。如果轴是综合时间的,则应在没有任何事件的时间上加一个空格。 @SergioPolimante 不!这不是热图轴刻度的工作方式。 是的,我想到了这一点,但是我的数据量很大,对数据进行重新采样并以分钟为单位创建丢失的数据会大大增加数据量。无论如何,我现在继续前进。我通常不会放弃这种编码挑战,但这个挑战让我受益匪浅,它对我所做的事情并不是必不可少的。无论如何,我真的很感谢你的帮助。谢谢。

以上是关于在 matplotlib 轴上格式化日期时间以获得小时和分钟的问题的主要内容,如果未能解决你的问题,请参考以下文章

在 matplotlib 中更改日期时间轴的格式

使用 Python 的 matplotlib 在 x 轴上绘制日期

如何使用 matplotlib 在日期时间轴上绘制一个矩形?

具有多列的 matplotlib 条形图,x 轴上的日期

如何在 r 汽车包中的后续情节的完整性中以适当的格式在 x 轴上绘制日期?

使用 Matplotlib 在 Python 中绘制时间