# Python使用Matplotlib绘制甘特图的实践

## 1.引言

Henry Gantt 为了分析已经完成的项目创建了甘特图，他最初设计这个可视化工具主要用来衡量员工的工作效率并从中识别表现不佳的员工。经过多年的发展，甘特图已经发展成项目规划和跟踪的必备工具。

## 2.举个栗子

```import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
```

```df = pd.read_excel("../data/plan.xlsx")
df
```

## 3.数据预处理

```# project start date
proj_start = df.Start.min()
# number of days from project start to task start
df["start_num"] = (df.Start - proj_start).dt.days
# number of days from project start to end of tasks
df["end_num"] = (df.End - proj_start).dt.days
# days between start and end of each task
df["days_start_to_end"] = df.end_num - df.start_num
```

## 4.绘制甘特图

Y轴表示任务名称，每个子项的宽度表示子任务开始和结束之间的天数，子项的起始位置为从项目开始到子任务开始之间的天数。

```fig, ax = plt.subplots(1, figsize=(16,6))
plt.show()
```

## 5.添加颜色

```# create a column with the color for each department
def color(row):
c_dict = {"MKT":"#E64646", "FIN":"#E69646", "ENG":"#34D05C", "PROD":"#34D0C3", "IT":"#3475D0"}
return c_dict[row["Department"]]
df["color"] = df.apply(color, axis=1)
```

```from matplotlib.patches import Patch
fig, ax = plt.subplots(1, figsize=(16,6))
##### LEGENDS #####
c_dict = {"MKT":"#E64646", "FIN":"#E69646", "ENG":"#34D05C",
"PROD":"#34D0C3", "IT":"#3475D0"}
legend_elements = [Patch(facecolor=c_dict[i], label=i)  for i in c_dict]
plt.legend(handles=legend_elements)
##### TICKS #####
xticks = np.arange(0, df.end_num.max()+1, 3)
xticks_labels = pd.date_range(proj_start, end=df.End.max()).strftime("%m/%d")
xticks_minor = np.arange(0, df.end_num.max()+1, 1)
ax.set_xticks(xticks)
ax.set_xticks(xticks_minor, minor=True)
ax.set_xticklabels(xticks_labels[::3])
plt.show()
```

## 6.添加透明度

```# days between start and current progression of each task
df["current_num"] = (df.days_start_to_end * df.Completion)
```

```from matplotlib.patches import Patch
fig, ax = plt.subplots(1, figsize=(16,6))
# bars
# texts
for idx, row in df.iterrows():
ax.text(row.end_num+0.1, idx,
f"{int(row.Completion*100)}%",
va="center", alpha=0.8)
##### LEGENDS #####
c_dict = {"MKT":"#E64646", "FIN":"#E69646", "ENG":"#34D05C", "PROD":"#34D0C3", "IT":"#3475D0"}
legend_elements = [Patch(facecolor=c_dict[i], label=i)  for i in c_dict]
plt.legend(handles=legend_elements)
##### TICKS #####
xticks = np.arange(0, df.end_num.max()+1, 3)
xticks_labels = pd.date_range(proj_start, end=df.End.max()).strftime("%m/%d")
xticks_minor = np.arange(0, df.end_num.max()+1, 1)
ax.set_xticks(xticks)
ax.set_xticks(xticks_minor, minor=True)
ax.set_xticklabels(xticks_labels[::3])
plt.show()
```

Wow,果真逼格满满。。。。