Кажется, что проще всего отсортировать информационный кадр по операции, а затем построить горизонтальные столбцы, используя индекс информационного кадра в качестве координаты y. Затем, изменяя пределы оси Y (устанавливая ее с высокого на низкое), получаются операции с наименьшим номером сверху. (В коде теперь предполагается, что каждый столбец будет находиться на новой строке, в то время как старый код предполагал, что для одной операции будет больше столбцов).
Поскольку теперь кажется, что операции принадлежат друг другу, цветовая карта с последовательными цветами выбирается, и цвета запускаются снова каждый раз, когда операция начинается раньше, чем предыдущая. Не стесняйтесь использовать любую схему, которая соответствует вашим целям.
Поскольку datetime.strptime
смотрит только на время, он получает дату по умолчанию (1 января 1900 года). Таким образом, ваш подход к использованию одного и того же преобразования для времени «сейчас» очень точен.
Обратите внимание, что анализатор типов pd.read_csv
дает формат с плавающей точкой для столбца операций. Вы можете предотвратить это, предоставив ему явную информацию о преобразовании. Например, pd.read_csv(..., converters={1: str})
чтобы иметь второй столбец в виде строки.
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime
import pandas as pd
import math
# % matplotlib inline
def timestr_to_num(timestr):
return mdates.date2num(datetime.strptime('0' + timestr if timestr[1] == ':' else timestr, '%I:%M:%S %p'))
plt.style.use('ggplot')
# df = pd.read_csv('zpp00141_new.csv')
columns = ['Operation short text', 'Operation/Activity', 'Earl. start / time', 'Latest finish / time']
rows = [['Mount right racks', '0250', '7:00:00 AM', '9:22:00 AM'],
['Mount right side motion unit carriage', '0251', '9:22:00 AM', '10:30:00 AM'],
['Mount left side motion unit carriage', '0252', '10:30:00 AM', '11:17:00 AM'],
['Install motion unit complete', '0253', '11:17:00 AM', '1:01:00 PM'],
['Move machine to next step + EPA', '0254', '1:01:00 PM', '3:30:00 PM'],
['Mount Left Racks', '0200', '7:00:00 AM', '9:12:00 AM'],
['Mount cable motor & Lubricate guide carr', '0201', '9:12:00 AM', '9:44:00 AM'],
['Mount suction components', '0202', '9:44:00 AM', '11:04:00 AM'],
['Mount extraction', '0203', '11:04:00 AM', '12:34:00 PM'],
['Mount temporary diamond plates', '0204', '12:34:00 PM', '1:04:00 PM'],
['Mount piping inside', '0205', '1:04:00 PM', '1:44:00 PM'],
['Move Machine to next step + EPA', '0206', '1:44:00 PM', '3:30:00 PM']]
df = pd.DataFrame(data=rows, columns=columns)
df.rename(columns={"Earl. start / time": "start", "Latest finish / time": "finish"}, inplace=True)
df['Operation/Activity'] = df['Operation/Activity'].astype(int)
df.sort_values('Operation/Activity', ascending=True, inplace=True, ignore_index=True)
fig, ax = plt.subplots(figsize=(10, 5))
#colors = plt.cm.tab10.colors # get a list of 10 colors
cmap = plt.cm.get_cmap('plasma_r')
colors = [cmap(i/9) for i in range(10)] # get a list of 10 colors
previous_start = math.inf # 'previous_start' helps to indicate we're starting again from the left
color_start = 0
for row in df.itertuples():
left = timestr_to_num(row.start)
right = timestr_to_num(row.finish)
if left <= previous_start:
color_start = row.Index
ax.barh(row.Index, left=left, width=right - left, height=1, color=colors[(row.Index - color_start) % len(colors)])
previous_start = left
ax.set_xlim(timestr_to_num('7: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
ax.set_xlabel('Time')
ax.set_ylabel('Operation')
ax.set_ylim(len(df), -1) # set the limits and reverse the order
ax.set_yticks(range(len(df)))
# ax.set_yticklabels(list(df['Operation/Activity']))
ax.set_yticklabels(list(df['Operation short text']))
now = datetime.now().strftime('%I:%M:%S %p')
ax.axvline(x=timestr_to_num(now),color='r')
plt.tight_layout()
plt.show()