我试图绘制计划的工作时间与实际工作时间的关系图,但是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 date date2num在x轴上捕获该日期?