Matplotlib Barh для запланированных часов против фактических отработанных часов - PullRequest
0 голосов
/ 19 сентября 2018

Я пытаюсь построить горизонтальную гистограмму для сотрудников, показывающую их запланированные часы работы против их фактических рабочих часов за данный день.

Я пробовал следующий код, но, как вы можете видеть в 'График 'ниже', он объединяет фактические отработанные часы (синий) до конца запланированных часов (зеленый).Кроме того, время на оси х не очень показательно.

Мне нужно иметь по два столбца для каждого сотрудника: зеленая полоса, показывающая запланированные часы вверху, и синяя полоса для фактического отработанного времени.под ним что-то вроде диаграммы Ганта.Кто-нибудь может помочь мне понять, где я ошибаюсь в своем коде?

#import stack
import pandas as pd
import datetime as dt
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

#dummy df
df = pd.DataFrame([['Bob', '2018-09-14 9:00:00', '2018-09-14 18:00:00', 'actual']
                   , ['Bob', '2018-09-14 9:15:00', '2018-09-14 18:30:00', 'scheduled']
                   , ['Kim', '2018-09-14 9:00:00', '2018-09-14 18:00:00', 'actual']
                   , ['Kim', '2018-09-14 8:45:00', '2018-09-14 17:30:00', 'scheduled']]
                   , columns=['name','start','finish', 'type'])

#convert timestamp columns to datetime
df[['start', 'finish']] = df[['start', 'finish']].apply(pd.to_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()

#generate plot
fig, ax = plt.subplots()
ax.barh(yval, width = actualWidth, left = actualStart, color = 'blue', height = 0.3, label = 'actual')
ax.barh(yval, width = scheduledWidth, left = scheduledStart, color = 'green', height = 0.3, label = 'scheduled')

#format x axis to time of day
xfmt = mdates.DateFormatter('%H:%m')
ax.xaxis.set_major_formatter(xfmt)

# autorotate the dates
fig.autofmt_xdate()
plt.show()

figure

1 Ответ

0 голосов
/ 19 сентября 2018

Попробуйте разные значения, такие как [0, 1] для первого и [0.3, 1.3] для второго ax.barh (чтобы они не перекрывались).Мы просто смещаем значение height.

ax.barh([0, 1], width = actualWidth, left = actualStart, color = 'blue', height = 0.3, label = 'actual')
ax.barh([0.3, 1.3], width = scheduledWidth, left = scheduledStart, color = 'green', height = 0.3, label = 'scheduled')

И меняем yticks (выбирая центр между двумя барами):

plt.yticks([0.15, 1.15], yval)

, наконец, чтобы исправить xtick:

fig.autofmt_xdate(ha='center')

example_figure

...