Как получить диаграмму Ганта с помощью matplotlib? - PullRequest
0 голосов
/ 12 февраля 2020

У меня есть следующие данные:

образец данных

Я хочу создать диаграмму Ганта, которая будет представлять временную шкалу в python. Я посмотрел другой пост, у которого была похожая проблема, но код не сработал для меня ( Как получить график Ганта с использованием 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» для столбцов, но он вызвал другую ошибку: «Недопустимый литерал для int () с основанием 10: '9: 22:00 утра ". Я был бы очень признателен за любую помощь в этом вопросе, так как я новичок в программировании на python. Если есть более простой и лучший способ представить то, что мне нужно, было бы полезно, если бы вы могли дать какие-либо советы. По сути, мне нужен график Ганта, чтобы представить каждое действие на «временной шкале» с 7 до 16:30 и отразить время «сейчас» в виде вертикальной линии на графике, чтобы указать, где мы сейчас находимся.

1 Ответ

1 голос
/ 13 февраля 2020

Если строки времени не в стандартном формате, datetime.strptime может использоваться для их преобразования. strptime нужно, чтобы все было заполнено нулями, поэтому приведенный ниже код проверяет, начинается ли строка с 1 или 2 цифр, и добавляет ли, при необходимости, ноль.

Вот пример, с которого можно начать. Я не набрал asp код в вопросе, так как некоторые столбцы отсутствуют. Кроме того, я изменил имена столбцов, чтобы они были совместимы с именами переменных, чтобы можно было использовать row.start вместо row[1].

Цвета можно назначать каждой операции, просто создавая их список , Matoplotlib имеет несколько встроенных цветовых карт , которые можно использовать. Например, «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()

example plot

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...