Построение диаграмм Ганна с цветовой кодировкой с использованием matplotlib и pandas - PullRequest
1 голос
/ 23 марта 2020

У меня есть код, который генерирует наложенную диаграмму Ганта с двумя наборами горизонтальных столбцов, один из которых указывает фактическое время для операции, а другой - плановое время для операции. Я хотел бы добавить цветовую настройку, чтобы мои фактические столбики (тонкие) имели разные цвета в разных случаях относительно «запланированного» времени. Вот условия-цвета:

Green - if the "actual" time for the operation is <= "planned"+10% (so it is green if the actual duration is within the `planned duration*1.1(10%)) and tolerance within 20%.
Red - if the actual time for the operation is >"planned"+10% or if the tolerance is <50%
Yellow -  if the "actual" start time is not within 20% tolerance (meaning that the operation didn't started +- on time) but less than 50% tolerance. 
For example, operation's duration is 60 minutes, planned start at 8:00 am. If the operation starts at 8:00+-60*20%(12 min). So the start time which would prompt yellow would be between 8:12(20%) and 8:30(50% tolerance) or 7:30(-50%) and 7:48(-20%).

Пожалуйста, помогите мне достичь этого, я предполагаю, что необходимо создать цветовую карту, но я не смог найти много информации с аналогичной реализацией в Интернете. Я был бы очень признателен за любую помощь. Вот картинка, которая бы прояснила случаи: Conditions

Вот мой код, который генерирует диаграмму Ганта:

import pandas as pd
from datetime import datetime
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import math
import time
import matplotlib.patches as mpatches
df = pd.read_csv('zpp00141_new.csv')
df1 = pd.read_csv('sample_data1.csv')
df = df.loc[df['Work Center'] == '503AL302']
df1 = df1.loc[df1['Work center'] == '503AL302']
#convert times to number to calculate
def timestr_to_num(timestr):
    return mdates.date2num(datetime.strptime('0' + timestr if timestr[1] == ':' else timestr, '%I:%M:%S %p'))
#gantt chart plotting
fig, ax = plt.subplots(figsize=(12.5, 6))
operations = pd.unique(df['Operation/Activity'])
#Declaring a colormap
cmap = plt.cm.get_cmap('plasma_r')
colors = [cmap(i/20) for i in range(20)]
#plot scheduled operations 
for operation, color in zip(operations, colors):
    for row in df[df['Operation/Activity'] == operation].itertuples():
        left = timestr_to_num(row.start)
        right = timestr_to_num(row.finish)
        ax.barh(operation, left=left, width=right - left, height=1, color="#6ED06F", edgecolor = 'black', label = operation)
#plot "Actual" operations' times     
operations1 = pd.unique(df1['Operation/Activity'])
for operation, color in zip(operations1, colors):
    for row in df1[df1['Operation/Activity'] == operation].itertuples():
        left = timestr_to_num(row.start)
        right = timestr_to_num(row.finish)
        ax.barh(operation, left=left, width=right - left, height=0.4, color='#33AFFF', edgecolor = 'black', label = operation)
        #plt.legend()
#set x-axis limit
ax.set_xlim(timestr_to_num('06:00:00 AM'), timestr_to_num('4:30:00 PM'))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))  # display ticks as hours and minutes
ax.xaxis.set_major_locator(mdates.HourLocator(interval=1))  # set a tick every hour
#set y and x labels
ax.set_xlabel('Time', fontsize = 'large')
ax.set_ylabel('Operation', fontsize = 'large')
plt.tight_layout()
ax.set_yticklabels(list(df['Operation/Activity'] + " - " + df['Operation short text'].astype(str)))
ax.tick_params(axis='both', which='major', labelsize=11)
#add a title to a plot
plt.title("Schedule", fontsize = 'x-large')
#convert "now" time to a certain format of hours:minutes:seconds am/pm and plot a vertical red line for the "Current time"
now = datetime.now()
now = now.strftime('%I:%M:%S %p')
plt.axvline(x=timestr_to_num(now),color='r', animated = True)
#adding the legend
patch = mpatches.Patch(color='#33AFFF', label='Actual')
patch2 = mpatches.Patch(color='#6ED06F', label='Planned')
plt.legend(handles=[patch, patch2], loc='upper left', fontsize = 'large')
plt.show()

Пример данных для zpp00141 (запланированный график ):

Operation short text,Operation/Activity,Earl. start / time,Latest finish / time,Work Center
Mount right racks,0250,7:00:00 AM,9:22:00 AM,503AL302
Mount right side motion unit carriage,0251,9:22:00 AM,10:30:00 AM,503AL302
Mount left side motion unit carriage,0252,10:30:00 AM,11:17:00 AM,503AL302
Install motion unit complete,0253,11:17:00 AM,1:01:00 PM,503AL302
Move machine to next step + EPA,0254,1:01:00 PM,3:30:00 PM,503AL302
Mount Left Racks,0200,7:00:00 AM,9:12:00 AM,503AL302
Mount cable motor & Lubricate guide carr,0201,9:12:00 AM,9:44:00 AM,503AL302
Mount suction components,0202,9:44:00 AM,11:04:00 AM,503AL302
Mount extraction,0203,11:04:00 AM,12:34:00 PM,503AL302
Mount temporary diamond plates,0204,12:34:00 PM,1:04:00 PM,503AL302
Mount piping inside,0205,1:04:00 PM,1:44:00 PM,503AL302
Move Machine to next step + EPA,0206,1:44:00 PM,3:30:00 PM,503AL302

Пример данных для zpp00138 (фактическое время):

Work center,Operation/Activity,Operation short text,Actual finish (time),Actual start (time)
503AL302,0201,Mount cable motor & Lubricate guide carr,10:22:26 AM,9:32:41 AM
503AL302,0202,Mount suction components,2:21:41 PM,10:23:03 AM
503AL302,0203,Mount extraction,2:22:58 PM,2:22:26 PM
503AL302,0204,Mount temporary diamond plates,2:24:28 PM,2:24:00 PM
503AL302,0250,Mount right racks,9:34:26 AM,6:02:45 AM
503AL302,0251,Mount right side motion unit carriage,10:50:17 AM,9:35:47 AM
503AL302,0253,Install motion unit complete,2:02:47 PM,12:28:33 PM
503AL302,0254,Move machine to next step + EPA,2:14:35 PM,2:02:58 PM
503AL302,0200,Mount Left Racks,9:30:59 AM,7:02:30 AM
503AL302,0205,Mount piping inside,2:25:23 PM,2:24:51 PM
503AL302,0206,Move Machine to next step + EPA,4:12:31 PM,2:26:39 PM
503AL302,0252,Mount left side motion unit carriage,12:28:22 PM,10:51:01 AM
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...