【问题标题】:How to get a gannt chart using matplotlib?如何使用 matplotlib 获取甘特图?
【发布时间】:2020-02-12 15:48:39
【问题描述】:

我有以下数据:

data sample

我想创建一个甘特图来表示 python 中的时间线。我查找了另一个有类似问题的帖子,但代码对我不起作用(How to get gantt plot using matplotlib),我无法自己解决问题。似乎它与我的“时间”值的数据类型有关。这是代码本身:

import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('zpp00141_new.csv')
df.dropna(subset=['Latest finish / time', 'Earl. start / time'])
#error when I try to change data type of the columns to int
df["Latest finish / time"]= df["Latest finish / time"].astype(int) 
df["Earl. start / time"]= df["Earl. start / time"].astype(int)
#error below with data types
df["Diff"] = df['Latest finish / time'] - df['Earl. start / time']
color = {"In":"turquoise", "Out":"crimson"}
fig,ax=plt.subplots(figsize=(6,3))

labels=[]
for i, task in enumerate(df.groupby("Operation/Activity")):
    labels.append(task[0])
    for r in task[1].groupby("Operation short text"):
        data = r[1][["Earl. start / time", "Diff"]]
        ax.broken_barh(data.values, (i-0.4,0.8), color=color[r[0]] )

ax.set_yticks(range(len(labels)))
ax.set_yticklabels(labels) 
ax.set_xlabel("time [ms]")
plt.tight_layout()       
plt.show()

我尝试将列的数据类型从对象转换为“int”,但它提示另一个错误:“invalid literal for int() with base 10: '9:22:00 AM'”。我真的很感激在这件事上的任何帮助,因为我对 python 编程很陌生。如果有一种更简单、更好的方法来表示我的需要,如果您能提供任何提示,那将会很有帮助。基本上,我需要一个甘特图来表示从早上 7 点到下午 4:30 的“时间轴”上的每个活动,并将“现在”时间反映为图表上的一条垂直线,以指示我们现在所处的位置。

【问题讨论】:

  • 也许this example 可以帮忙?
  • 感谢您提供此示例,但我的时间格式不同:h:min:sec AM/PM。我需要图表来显示从早上 7 点到下午 4:30 的时间线,以每小时为间隔。作为数据输入,我使用 csv 文件,其中包含按特定操作/活动分类的开始时间和结束时间。如果您不介意告诉我,我将如何针对这些要求修改代码?

标签: python pandas dataframe matplotlib


【解决方案1】:

当时间字符串不是标准格式时,可以使用datetime.strptime进行转换。 strptime 需要将所有内容都补零,因此下面的代码会检查字符串是否以 1 位或 2 位数字开头,并在需要时添加零。

这是一个让您入门的示例。我没有掌握问题中的代码,因为某些列似乎丢失了。另外,我更改了列的名称以与变量名称兼容,以便能够使用row.start 而不是row[1]

可以为每个操作分配颜色,只需创建它们的列表。 Matoplotlib 有一些可以使用的built-in colormaps。例如,“tab10”有 10 种不同的颜色。如果每个单独的操作没有足够的颜色,可以重复该列表。

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime
import math

def timestr_to_num(timestr):
    return mdates.date2num(datetime.strptime('0' + timestr if timestr[1] == ':' else timestr, '%I:%M:%S %p'))

df = pd.DataFrame({'start': ['7:00:00 AM', '1:00:00 PM', '7:20:00 AM', '2:00:00 PM'],
                   'finish': ['12:15:00 PM', '4:20:00 PM', '1:10:00 PM', '3:30:00 PM'],
                   'operation': ['operation 1', 'operation 1', 'operation 2', 'operation 3'],
                   'short_text': ['short text 1', 'short text 2', 'short text 1', 'short text 2']})
fig, ax = plt.subplots(figsize=(10, 3))
operations = pd.unique(df['operation'])
colors = plt.cm.tab10.colors  # get a list of 10 colors
colors *= math.ceil(len(operations) / (len(colors)))  # repeat the list as many times as needed
for operation, color in zip(operations, colors):
    for row in df[df['operation'] == operation].itertuples():
        left = timestr_to_num(row.start)
        right = timestr_to_num(row.finish)
        ax.barh(operation, left=left, width=right - left, height=0.8, color=color)
ax.set_xlim(timestr_to_num('07: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
plt.tight_layout()
plt.show()

【讨论】:

  • 感谢代码,但如果我的数据中没有“输入/输出”列怎么办。我只有时间。在这种情况下如何分配颜色?我希望看到每个操作都有不同的颜色,但我不想手动为每个操作指定颜色,我希望颜色是随机选择的,或者在所有操作中都相同。在这种情况下,代码会有什么不同?
  • 非常感谢,在您的帮助下,我能够绘制甘特图!
  • 您能否就如何在 x 轴上绘制一条与当前时间相对应的垂直红线提出建议?我尝试使用 plt.axvline 但我不知道如何转换它以使其适用于我的格式和数据。提前非常感谢!
猜你喜欢
  • 2017-09-08
  • 2013-08-06
  • 2019-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-15
  • 1970-01-01
相关资源
最近更新 更多