13-February-2025M | 14-Shaban-1446H

ALVINBURHANI.NET

MUHAMMAD BURHANUDDIN BLOGSITE

Gantt Chart dengan Python

Views: 20
2 0
Read Time:6 Minute, 25 Second

Dengan sejarah lebih dari 100 tahun, visualisasi ini terus sangat berguna untuk manajemen proyek. Henry Gantt awalnya membuat grafik untuk menganalisis proyek yang telah selesai. Lebih khusus lagi, ia merancang visualisasi ini untuk mengukur produktivitas dan mengidentifikasi karyawan yang berkinerja buruk. Selama bertahun-tahun, itu menjadi alat untuk perencanaan dan pelacakan, sering dibuang setelah proyek selesai.

Tidak dapat dipungkiri bahwa bagan Gantt telah banyak berubah sejak desain pertamanya. Analis memperkenalkan banyak pengkodean untuk menampilkan perbedaan antara departemen, kelengkapan tugas, dependensi, tenggat waktu, dan banyak lagi. Artikel ini akan mengeksplorasi cara membuat bagan Gantt menggunakan Python, Pandas, dan Matplotlib.

Untuk contoh ini, kita akan membutuhkan beberapa data dummy; himpunan data yang akan kita gunakan memiliki kolom untuk nama tugas (Task), departemen, tanggal mulai dan berakhir, dan penyelesaian dengan struktur data seperti tabel dibawah ini:

TaskDepartmentStartEndCompletion
TASK MIT17-Mar-2220-Mar-220
TASK NMKT17-Mar-2219-Mar-220
TASK LENG10-Mar-2213-Mar-220
TASK KPROD9-Mar-2213-Mar-220
TASK JPROD4-Mar-2217-Mar-220
TASK HFIN28-Feb-222-Mar-221
TASK IMKT28-Feb-225-Mar-220.4
TASK GFIN27-Feb-223-Mar-220.7
TASK FMKT26-Feb-2227-Feb-221
TASK EENG23-Feb-229-Mar-220.5
TASK DFIN22-Feb-221-Mar-221
TASK CIT21-Feb-223-Mar-220.9
TASK BMKT19-Feb-2224-Feb-221
TASK AMKT15-Feb-2220-Feb-221

Kemudian, menambahkan kolom dengan jumlah hari dari awal proyek hingga awal setiap tugas; Ini akan membantu memposisikan batang pada sumbu x. Sama juga untuk akhir tugas; maka ini akan memfasilitasi penghitungan total hari yang diperlukan untuk menyelesaikan task, panjang bar, dan membantu memposisikan teks di kemudian nanti.

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
 
df = pd.read_excel('plan.xlsx')
 
# 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

Sekarang kita dapat memplot bagan batang. Y akan menjadi nama tugas, lebarnya adalah jumlah hari antara awal dan akhir tugas, dan kiri adalah jumlah hari antara proyek dimulai hingga tugas dimulai.

# 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))
ax.barh(df.Task, df.days_start_to_end, left=df.start_num, color=df.color)
##### 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()

Sekarang kode kelengkapan proyek ke visualisasi dimana untuk meningkatkan presisi, persentase progress dituliskan di akhir grafik batang, dan untuk membedakan yang sudah selesai dari yang belum selesai, parameter alfa (transparensi) pada grafik juga divisualisasikan.

# 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
ax.barh(df.Task, df.current_num, left=df.start_num, color=df.color)
ax.barh(df.Task, df.days_start_to_end, left=df.start_num, color=df.color, alpha=0.5)
# 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()

Untuk membuatnya lebih menarik, menambahkan lebih banyak informasi dengan sumbu lain, menggambar garis kisi-kisi, menambahkan judul, dan banyak lagi. Memecah tugas, melacak ukuran kinerja, dependensi, pencapaian, tenggat waktu, dan banyak lagi. Menambahkan lebih banyak informasi ke bagan Gantt akan sangat mudah dicapai dengan lebih banyak pengkodean, tooltip, penelusuran detail, dan teks.

Berikut versi lengkapnya

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Patch
from pandas import Timestamp
 
# 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
 
# days between start and current progression of each task
df['current_num'] = (df.days_start_to_end * df.Completion)
 
# 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)
 
##### PLOT #####
fig, (ax, ax1) = plt.subplots(2, figsize=(16,6), gridspec_kw={'height_ratios':[6, 1]}, facecolor='#36454F')
ax.set_facecolor('#36454F')
ax1.set_facecolor('#36454F')
# bars
ax.barh(df.Task, df.current_num, left=df.start_num, color=df.color)
ax.barh(df.Task, df.days_start_to_end, left=df.start_num, color=df.color, alpha=0.5)
 
for idx, row in df.iterrows():
ax.text(row.end_num+0.1, idx, f"{int(row.Completion*100)}%", va='center', alpha=0.8, color='w')
ax.text(row.start_num-0.1, idx, row.Task, va='center', ha='right', alpha=0.8, color='w')
 
# grid lines
ax.set_axisbelow(True)
ax.xaxis.grid(color='k', linestyle='dashed', alpha=0.4, which='both')
 
# 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], color='w')
ax.set_yticks([])
 
plt.setp([ax.get_xticklines()], color='w')
 
# align x axis
ax.set_xlim(0, df.end_num.max())
 
# remove spines
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['left'].set_position(('outward', 10))
ax.spines['top'].set_visible(False)
ax.spines['bottom'].set_color('w')
 
plt.suptitle('PROJECT ALVINBURHANI.NET', color='w')
 
##### LEGENDS #####
legend_elements = [Patch(facecolor='#E64646', label='Marketing'),
Patch(facecolor='#E69646', label='Finance'),
Patch(facecolor='#34D05C', label='Engineering'),
Patch(facecolor='#34D0C3', label='Production'),
Patch(facecolor='#3475D0', label='IT')]
 
legend = ax1.legend(handles=legend_elements, loc='upper center', ncol=5, frameon=False)
plt.setp(legend.get_texts(), color='w')
 
# clean second axis
ax1.spines['right'].set_visible(False)
ax1.spines['left'].set_visible(False)
ax1.spines['top'].set_visible(False)
ax1.spines['bottom'].set_visible(False)
ax1.set_xticks([])
ax1.set_yticks([])
 
# Get "Today" value from sys date/ date.today()
#from datetime import date
#today = pd.Timestamp(date.today())
#today = today - proj_start
 
# Get "Today" value from custom timestamp
today = Timestamp('2022-03-02 00:00:00') 
today = today - proj_start
 
# plot line for today
ax.axvline(today.days, color='w', lw=1, alpha=0.7)
ax.text(today.days, len(df)+0.5, 'Today', ha='center', color='w')
 
plt.show()

OutPut:

Terima kasih telah membaca artikel ini, semoga bermanfaat.

About Post Author

Muh. Burhanuddin

Industrial Engineer, Specialist in Heavy Cargo Transportation and Heavy Lifting Works. Hobby in computer programming, reading and writing. No occupation except waiting for a prayer time. Ready for working as a surveyor, transport planer, or as lifting engineer.
Happy
Happy
0 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %

About The Author

More Stories

Be the first to write a review

Average Rating

5 Star
0%
4 Star
0%
3 Star
0%
2 Star
0%
1 Star
0%

Leave a Reply

Your email address will not be published. Required fields are marked *

You may have missed