最简单的方法似乎是按操作对数据帧进行排序,然后使用数据帧的索引作为 y 坐标绘制水平条。然后,反转 y 轴的限制(将其从高到低设置),将编号最低的操作放在顶部。 (现在的代码假设每个条形图都位于一个新行,而旧代码假设一次操作会有更多条形图)。
由于操作现在似乎属于在一起,因此选择具有连续颜色的颜色图,并且每次操作比前一个操作更早开始时,颜色都会重新开始。请随意使用任何适合您目标的方案。
As the datetime.strptime
只查看时间,它会获得默认日期(1900 年 1 月 1 日)。因此,您在“现在”时间使用相同转换的方法是非常适当的。
注意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()