Views: 189 4 0 Read Time:6 Minute, 25 SecondDengan 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:TaskDepartmentStartEndCompletionTASK MIT17-Mar-2220-Mar-220TASK NMKT17-Mar-2219-Mar-220TASK LENG10-Mar-2213-Mar-220TASK KPROD9-Mar-2213-Mar-220TASK JPROD4-Mar-2217-Mar-220TASK HFIN28-Feb-222-Mar-221TASK IMKT28-Feb-225-Mar-220.4TASK GFIN27-Feb-223-Mar-220.7TASK FMKT26-Feb-2227-Feb-221TASK EENG23-Feb-229-Mar-220.5TASK DFIN22-Feb-221-Mar-221TASK CIT21-Feb-223-Mar-220.9TASK BMKT19-Feb-2224-Feb-221TASK AMKT15-Feb-2220-Feb-221Kemudian, 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_numimport pandas as pd import matplotlib.pyplot as plt import numpy as npdf = 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_numSekarang 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()# 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()# 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 lengkapnya1 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()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.Share Facebook Twitter LinkedIn 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. https://www.alvinburhani.net Happy 0 0 % Sad 0 0 % Excited 1 100 % Sleepy 0 0 % Angry 0 0 % Surprise 0 0 % Post navigationPemilihan Lokasi Gudang Beban Dinamis Cargo Transportasi Laut