首页 > 解决方案 > Python 3 - 在 x 轴上绘制小时数时,matplotlib 无法识别时区

问题描述

我正在尝试绘制计划的工作时间与实际工作时间,但 x 轴上的时间无法识别时区偏移量。

这是我正在使用的代码示例:

### Import stack
import pandas as pd
import datetime
from datetime import datetime as dt
from datetime import date, timedelta 
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

### build dummy shifts df
shifts = [{'name': 'Bob', 'start': '2018-10-13 20:00:00+13:00', 'finish': '2018-10-14 03:00:00+13:00', 'type': 'scheduled'},
          {'name': 'Bob', 'start': '2018-10-13 20:30:00+13:00', 'finish': '2018-10-14 03:02:00+13:00', 'type': 'actual'},
          {'name': 'Joe', 'start': '2018-10-13 22:00:00+13:00', 'finish': '2018-10-14 03:00:00+13:00', 'type': 'scheduled'},
          {'name': 'Joe', 'start': '2018-10-13 22:00:00+13:00', 'finish': '2018-10-14 02:06:00+13:00', 'type': 'actual'},
          {'name': 'Sally', 'start': '2018-10-13 18:30:00+13:00', 'finish': '2018-10-14 03:00:00+13:00', 'type': 'scheduled'},
          {'name': 'Sally', 'start': '2018-10-13 18:30:00+13:00', 'finish': '2018-10-14 02:05:00+13:00', 'type': 'actual'}]
df = pd.DataFrame(shifts)

df['start'] = pd.to_datetime(df['start'].apply(pd.Timestamp))
df['finish'] = pd.to_datetime(df['finish'].apply(pd.Timestamp))


### Plot of scheduled vs. actual hours
hours = mdates.HourLocator() # every hour
minutes = mdates.MinuteLocator(interval= 30)  # every 30 mins
hoursFmt = mdates.DateFormatter('%I %p')

xStart = (df[['start']].min() - timedelta(hours = 1)).astype(datetime.datetime)
xEnd = (df[['finish']].max() + timedelta(hours = 1)).astype(datetime.datetime)

#scheduled time period
scheduledStart = mdates.date2num(df['start'][(df['type'] == 'scheduled')].dt.to_pydatetime())
scheduledEnd =  mdates.date2num(df['finish'][(df['type'] == 'scheduled')].dt.to_pydatetime())
scheduledWidth = scheduledEnd - scheduledStart

#actual time period
actualStart = mdates.date2num(df['start'][(df['type'] == 'actual')].dt.to_pydatetime())
actualEnd =  mdates.date2num(df['finish'][(df['type'] == 'actual')].dt.to_pydatetime())
actualWidth = actualEnd - actualStart

#y axis values
yval = df['name'].unique()
actualYTicks = [index for index, value in enumerate(actualStart)]
scheduledYTicks = [x+0.3 for x in actualYTicks]
yTicks = [sum(x)/2 for x in zip(actualYTicks, scheduledYTicks)]

#generate plot
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.barh(scheduledYTicks, width = scheduledWidth, left = scheduledStart, color = 'lightgrey', height = 0.3, label = 'Scheduled Hours')
ax.barh(actualYTicks, width = actualWidth, left = actualStart, color = 'green', height = 0.3, label = 'Actual Hours')

#format x axis to time of day
ax.xaxis.set_major_locator(hours)
ax.xaxis.set_major_formatter(hoursFmt)
ax.xaxis.set_minor_locator(minutes)

# autorotate the dates
fig.autofmt_xdate()
plt.yticks(yTicks, yval)
ax.set_xlim([mdates.date2num(xStart), mdates.date2num(xEnd)])

#extract legend labels
handles, labels = ax.get_legend_handles_labels()
lgd = ax.legend(handles, labels, loc= 'upper center', bbox_to_anchor=(0.5,-0.1))

plt.show()

计划与实际工作时间

该图表的格式是我希望它在图像中看到的样子,但 x 轴上的小时数不正确。Sally 实际预定于当地时间上午 7:30 开始,于 10 月 14 日当地时间下午 4:00 结束。开始日期和结束日期是“太平洋/奥克兰”时区,那么为什么不使用 matplotlib 日期 date2num 在 x 轴上捕获呢?

标签: python-3.xmatplotlibtimezonetimezone-offset

解决方案


推荐阅读