Trong hướng dẫn từng bước này, chúng ta sẽ bàn về biểu đồ Gantt là gì, vì sao và khi nào kiểu trực quan hóa này hữu ích, cách tạo biểu đồ Gantt trong Python với matplotlib, và cách tùy chỉnh thêm. Trong quá trình đó, chúng ta sẽ xây dựng một số ví dụ biểu đồ Gantt bằng matplotlib.
Biểu đồ Gantt là gì và vì sao nó hữu ích?
Biểu đồ Gantt là một dạng biểu đồ cột dùng để minh họa lịch trình lập kế hoạch và quản lý dự án hoàn chỉnh. Nó thường hiển thị các thông tin như tên nhiệm vụ của dự án, ngày bắt đầu và kết thúc, nhóm phụ trách nhiệm vụ, trạng thái hoàn thành dưới dạng phần trăm hoặc phân số, hiệu suất theo nhóm, và các cột mốc quan trọng của dự án.
Tên nhiệm vụ được sắp xếp dọc theo trục y của biểu đồ Gantt, thường được sắp theo thứ tự thời gian của ngày bắt đầu từ trên xuống dưới. Trục x dùng để hiển thị các khoảng thời gian, với độ rộng của mỗi thanh tương ứng với thời lượng thực hiện của từng nhiệm vụ.
Vì biểu đồ Gantt về bản chất là một dạng cụ thể của biểu đồ cột ngang, ta có thể tạo nó trong nhiều thư viện trực quan hóa dữ liệu của Python, gồm matplotlib, Plotly, Bokeh và Altair. Trong hướng dẫn này, chúng ta sẽ tập trung vào việc tạo biểu đồ Gantt trong thư viện phổ biến nhất – matplotlib.
Cách tạo biểu đồ Gantt trong Python với Matplotlib
Sử dụng barh()
Bắt đầu với việc dựng một biểu đồ Gantt cơ bản bằng matplotlib sử dụng phương thức barh() của matplotlib.pyplot.
Trước hết, ta cần tải các thư viện cần thiết:
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import datetime as dtĐược hỗ trợ bởi
Bước tiếp theo là tạo dữ liệu giả để thực hành:
df = pd.DataFrame({'task':['A','B','C','D','E','F','G','H','I','J','K','L'],'team':['R&D','Accounting','Sales','Sales','IT','R&D','IT','Sales','Accounting','Accounting','Sales','IT'],'start': pd.to_datetime(['20 Oct 2022','24 Oct 2022','26 Oct 2022','31 Oct 2022','3 Nov 2022','7 Nov 2022','10 Nov 2022','14 Nov 2022','18 Nov 2022','23 Nov 2022','28 Nov 2022','30 Nov 2022']),'end': pd.to_datetime(['31 Oct 2022','28 Oct 2022','31 Oct 2022','8 Nov 2022','9 Nov 2022','18 Nov 2022','17 Nov 2022','22 Nov 2022','23 Nov 2022','1 Dec 2022','5 Dec 2022','5 Dec 2022']),'completion_frac':[1,1,1,1,1,0.95,0.7,0.35,0.1,0,0,0]})print(df)Được hỗ trợ bởi
Kết quả:
task team start end completion_frac
0 A R&D 2022-10-202022-10-311.001 B Accounting 2022-10-242022-10-281.002 C Sales 2022-10-262022-10-311.003 D Sales 2022-10-312022-11-081.004 E IT 2022-11-032022-11-091.005 F R&D 2022-11-072022-11-180.956 G IT 2022-11-102022-11-170.707 H Sales 2022-11-142022-11-220.358 I Accounting 2022-11-182022-11-230.109 J Accounting 2022-11-232022-12-010.0010 K Sales 2022-11-282022-12-050.0011 L IT 2022-11-302022-12-050.00Được hỗ trợ bởi
Để thuận tiện cho việc dựng biểu đồ Gantt cho dữ liệu này, chúng ta cần tính thêm bốn cột đại diện cho các thông tin sau:
Số ngày đã/sẽ trôi qua từ lúc dự án bắt đầu tới ngày bắt đầu của mỗi nhiệm vụ:
df['days_to_start']=(df['start']- df['start'].min()).dt.daysĐược hỗ trợ bởi
Số ngày đã/sẽ trôi qua từ lúc dự án bắt đầu tới ngày kết thúc của mỗi nhiệm vụ:
df['days_to_end']=(df['end']- df['start'].min()).dt.daysĐược hỗ trợ bởi
Thời lượng của mỗi nhiệm vụ, bao gồm cả ngày bắt đầu và ngày kết thúc:
df['task_duration']= df['days_to_end']- df['days_to_start']+1# to include also the end dateĐược hỗ trợ bởi
Trạng thái hoàn thành của mỗi nhiệm vụ chuyển từ phân số sang số ngày phân bổ cho nhiệm vụ đó:
df['completion_days']= df['completion_frac']* df['task_duration']Được hỗ trợ bởi
task team start end completion_frac days_to_start \
0 A R&D 2022-10-202022-10-311.0001 B Accounting 2022-10-242022-10-281.0042 C Sales 2022-10-262022-10-311.0063 D Sales 2022-10-312022-11-081.00114 E IT 2022-11-032022-11-091.00145 F R&D 2022-11-072022-11-180.95186 G IT 2022-11-102022-11-170.70217 H Sales 2022-11-142022-11-220.35258 I Accounting 2022-11-182022-11-230.10299 J Accounting 2022-11-232022-12-010.003410 K Sales 2022-11-282022-12-050.003911 L IT 2022-11-302022-12-050.0041
days_to_end task_duration completion_days
0111212.001855.0021166.0031999.0042077.005291211.4062885.6073393.1583460.6094290.00104680.00114660.00Được hỗ trợ bởi
Bây giờ, chúng ta sẵn sàng tạo một biểu đồ Gantt cơ bản trong matplotlib:
plt.barh(y=df['task'], width=df['task_duration'], left=df['days_to_start'])
plt.show()Được hỗ trợ bởi
Kết quả:
Biểu đồ trên cần khá nhiều điều chỉnh để chúng ta có thể rút trích tối đa thông tin từ đó:
Thêm tiêu đề ý nghĩa và nhãn trục x (các ngày)
Đảo ngược trục y để các nhiệm vụ theo thứ tự thời gian từ trên xuống dưới
Thêm lưới
Tô màu nhiệm vụ theo nhóm
Hiển thị chú giải
Thêm trạng thái hoàn thành nhiệm vụ
Chúng ta sẽ sớm triển khai tất cả những tinh chỉnh đó. Tuy nhiên, trước khi làm vậy, hãy xem cách xử lý việc tạo biểu đồ Gantt cơ bản.
Sử dụng broken_barh()
Khi một số nhiệm vụ có hai hoặc nhiều phân nhiệm trải dài theo thời gian, chúng ta nên dùng một phương thức khác của matplotlib – broken_barh().
Để có dữ liệu giả để thử cách tiếp cận này, hãy làm như sau:
Lấy từ dataframe ban đầu những nhiệm vụ được giao cho nhóm Sales (tạm thời bỏ qua cột completion_frac).
Đổi tên cột start và end thành start_1 và end_1 tương ứng (cho tiện).
Thêm nhiều phân nhiệm cho một số nhiệm vụ hiện có.
Với mỗi phân nhiệm, tính ba cột như trên, biểu diễn các thông tin sau:
Số ngày đã/sẽ trôi qua từ lúc dự án bắt đầu tới ngày bắt đầu của từng phân nhiệm.
Số ngày đã/sẽ trôi qua từ lúc dự án bắt đầu tới ngày kết thúc của từng phân nhiệm.
Thời lượng của từng phân nhiệm, bao gồm cả ngày bắt đầu và ngày kết thúc.
# 1
df2 = df[df['team']=='Sales'][['task','team','start','end']]# 2
df2.rename(columns={'start':'start_1','end':'end_1'}, inplace=True)
df2.reset_index(drop=True, inplace=True)# 3
df2['start_2']= pd.to_datetime([None,'10 Nov 2022','25 Nov 2022',None])
df2['end_2']= pd.to_datetime([None,'14 Nov 2022','28 Nov 2022',None])
df2['start_3']= pd.to_datetime([None,None,'1 Dec 2022',None])
df2['end_3']= pd.to_datetime([None,None,'5 Dec 2022',None])# 4for i in[1,2,3]:
suffix ='_'+str(i)
df2['days_to_start'+ suffix]=(df2['start'+ suffix]- df2['start_1'].min()).dt.days
df2['days_to_end'+ suffix]=(df2['end'+ suffix]- df2['start_1'].min()).dt.days
df2['task_duration'+ suffix]= df2['days_to_end'+ suffix]- df2['days_to_start'+ suffix]+1print(df2)Được hỗ trợ bởi
Kết quả:
task team start_1 end_1 start_2 end_2 start_3 \
0 C Sales 2022-10-262022-10-31 NaT NaT NaT
1 D Sales 2022-10-312022-11-082022-11-102022-11-14 NaT
2 H Sales 2022-11-142022-11-222022-11-252022-11-282022-12-013 K Sales 2022-11-282022-12-05 NaT NaT NaT
end_3 days_to_start_1 days_to_end_1 task_duration_1 \
0 NaT 0561 NaT 513922022-12-05192793 NaT 33408
days_to_start_2 days_to_end_2 task_duration_2 days_to_start_3 \
0 NaN NaN NaN NaN
115.019.05.0 NaN
230.033.04.036.03 NaN NaN NaN NaN
days_to_end_3 task_duration_3
0 NaN NaN
1 NaN NaN
240.05.03 NaN NaN Được hỗ trợ bởi
Lưu ý rằng giờ đây nhiệm vụ D có hai phân nhiệm, nhiệm vụ H có ba phân nhiệm, còn C và K mỗi nhiệm vụ có một phân nhiệm. Vì vậy, D và H là những nhiệm vụ mà chúng ta sẽ áp dụng phương thức broken_barh(). Do cú pháp của phương thức này kém trực quan hơn barh(), hãy xem các tham số chính và định dạng của chúng. Các tham số bắt buộc của broken_barh() là:
xranges – một dãy các bộ giá trị theo định dạng (xmin, xwidth) để chỉ điểm bắt đầu và độ dài của mỗi thanh. Tại đây, mỗi thanh đại diện cho một phân nhiệm. Vậy tham số này hiển thị ngày bắt đầu và thời lượng của mỗi phân nhiệm.
yrange – một bộ giá trị theo định dạng (ymin, yheight) để chỉ vị trí y và chiều cao cho mỗi thanh.
Bây giờ, hãy vẽ biểu đồ Gantt "gãy đoạn" của chúng ta. Thuật toán như sau:
Tạo một figure với các subplot.
Lặp qua các hàng của dataframe và kiểm tra nhiệm vụ có một, hai hay ba phân nhiệm. Dựa vào đó, thực hiện:
Một phân nhiệm: vẽ một thanh bằng phương thức barh() như trước.
Hai phân nhiệm: vẽ hai thanh bằng phương thức broken_barh().
Ba phân nhiệm: vẽ ba thanh bằng phương thức broken_barh().
Thêm điều chỉnh cơ bản: đặt và gán nhãn các tick của trục y.
Trong đoạn mã trên, thực ra chúng ta có thể dùng phương thức broken_barh() để vẽ các thanh cả cho những nhiệm vụ chỉ có một phân nhiệm. Khi đó, cần thay dòng:
ax.barh(y=df2['task'], width=df2['task_duration_1'], left=df2['days_to_start_1'])Được hỗ trợ bởi
bằng dòng này:
ax.broken_barh(xranges=[(row['days_to_start_1'], row['task_duration_1'])], yrange=(index +1,0.5))Được hỗ trợ bởi
Cách này cũng giúp mã của chúng ta đồng nhất và dễ đọc hơn.
task team start end completion_frac days_to_start \
0 A R&D 2022-10-202022-10-311.0001 B Accounting 2022-10-242022-10-281.0042 C Sales 2022-10-262022-10-311.0063 D Sales 2022-10-312022-11-081.00114 E IT 2022-11-032022-11-091.00145 F R&D 2022-11-072022-11-180.95186 G IT 2022-11-102022-11-170.70217 H Sales 2022-11-142022-11-220.35258 I Accounting 2022-11-182022-11-230.10299 J Accounting 2022-11-232022-12-010.003410 K Sales 2022-11-282022-12-050.003911 L IT 2022-11-302022-12-050.0041
days_to_end task_duration completion_days
0111212.001855.0021166.0031999.0042077.005291211.4062885.6073393.1583460.6094290.00104680.00114660.00Được hỗ trợ bởi
và biểu đồ Gantt đầu tiên của chúng ta:
plt.barh(y=df['task'], width=df['task_duration'], left=df['days_to_start'])
plt.show()Được hỗ trợ bởi
Kết quả:
Cụ thể, chúng ta muốn thêm một số tùy chỉnh vào biểu đồ này để nó giàu thông tin hơn.
Một điều còn thiếu trong ví dụ biểu đồ Gantt trên là chú giải thể hiện màu nào ứng với nhóm nào. Để khắc phục, hãy tạo các patch – đối tượng đồ họa 2D của matplotlib được tô bằng một màu xác định trước. Chúng ta sẽ dùng lớp matplotlib.patches.Patch để tạo danh sách patch, mỗi nhóm một patch, tô màu tương ứng:
patches =[]for team in team_colors:
patches.append(matplotlib.patches.Patch(color=team_colors[team]))Được hỗ trợ bởi
Giờ chúng ta sẵn sàng thêm chú giải vào biểu đồ:
fig, ax = plt.subplots()for index, row in df.iterrows():
plt.barh(y=row['task'], width=row['task_duration'], left=row['days_to_start']+1, color=team_colors[row['team']])
plt.title('Project Management Schedule of Project X', fontsize=15)
plt.gca().invert_yaxis()
ax.set_xticks(xticks)
ax.set_xticklabels(xticklabels[::7])
ax.xaxis.grid(True, alpha=0.5)# Adding a legend
ax.legend(handles=patches, labels=team_colors.keys(), fontsize=11)
plt.show()Được hỗ trợ bởi
Kết quả:
Ví dụ biểu đồ Gantt trên trông nhiều thông tin hơn hẳn.
Cho đến giờ, chúng ta vẫn chưa dùng cột completion_days đã tính ở đầu hướng dẫn. Bây giờ, chúng ta sẽ dùng nó để làm cho biểu đồ Gantt mang nhiều thông tin hơn bằng cách hiển thị giai đoạn hoàn thành của mỗi nhiệm vụ.
Về kỹ thuật, chúng ta sẽ thêm một thanh nữa chồng lên mỗi thanh đã vẽ. Thanh dưới biểu diễn tổng thời lượng của mỗi nhiệm vụ theo số ngày được phân bổ, trong khi thanh trên biểu diễn trạng thái hoàn thành của nhiệm vụ đó theo số ngày được phân bổ.
Với mỗi nhiệm vụ, cả hai thanh sẽ có cùng một màu theo nhóm tương ứng, nhưng thanh dưới sẽ nhạt màu hơn thanh trên để dễ phân biệt.
Nói cách khác, nếu một nhóm đang vượt tiến độ ở một nhiệm vụ, sự kết hợp của hai thanh sẽ cho thấy như thể nhóm đã làm nhiều ngày cho nhiệm vụ đó hơn dự kiến (nghĩa là nhiệm vụ có khả năng hoàn thành trước hạn).
Ở chiều ngược lại, nếu một nhóm đang chậm tiến độ ở một nhiệm vụ, sự kết hợp các thanh tương ứng sẽ cho thấy như thể nhóm làm ít ngày hơn dự kiến (nghĩa là nhiệm vụ có khả năng hoàn thành sau hạn).
fig, ax = plt.subplots()for index, row in df.iterrows():# Adding a lower bar - for the overall task duration
plt.barh(y=row['task'], width=row['task_duration'], left=row['days_to_start']+1, color=team_colors[row['team']], alpha=0.4)# Adding an upper bar - for the status of completion
plt.barh(y=row['task'], width=row['completion_days'], left=row['days_to_start']+1, color=team_colors[row['team']])
plt.title('Project Management Schedule of Project X', fontsize=15)
plt.gca().invert_yaxis()
ax.set_xticks(xticks)
ax.set_xticklabels(xticklabels[::7])
ax.xaxis.grid(True, alpha=0.5)
ax.legend(handles=patches, labels=team_colors.keys(), fontsize=11)
plt.show()Được hỗ trợ bởi
Kết quả:
Từ biểu đồ trên, ta thấy các nhóm không có cùng nhịp độ hoàn thành nhiệm vụ, điều khá phổ biến trong nhiều dự án thực tế. Để rút thêm thông tin, giả sử ngày hiện tại là 17/11/2022 và đánh dấu ngày này trên biểu đồ:
fig, ax = plt.subplots()for index, row in df.iterrows():
plt.barh(y=row['task'], width=row['task_duration'], left=row['days_to_start']+1, color=team_colors[row['team']], alpha=0.4)
plt.barh(y=row['task'], width=row['completion_days'], left=row['days_to_start']+1, color=team_colors[row['team']])
plt.title('Project Management Schedule of Project X', fontsize=15)
plt.gca().invert_yaxis()
ax.set_xticks(xticks)
ax.set_xticklabels(xticklabels[::7])
ax.xaxis.grid(True, alpha=0.5)
ax.legend(handles=patches, labels=team_colors.keys(), fontsize=11)# Marking the current date on the chart
ax.axvline(x=29, color='r', linestyle='dashed')
ax.text(x=29.5, y=11.5, s='17/11', color='r')
plt.show()Được hỗ trợ bởi
Kết quả:
Chúng ta có thể đưa ra các nhận xét sau về trạng thái hiện tại của Project X:
Nhóm R&D đang vượt tiến độ ở Nhiệm vụ F và có thể sẽ hoàn thành trước hạn.
Nhóm IT đang chậm ở Nhiệm vụ G và có lẽ cần được hỗ trợ.
Nhóm Sales đang thực hiện đúng lịch ở Nhiệm vụ H.
Nhóm Accounting đã bắt đầu Nhiệm vụ I sớm hơn lịch dự án.
Những nhận xét như vậy có thể giúp các trưởng nhóm và quản lý dự án điều chỉnh lịch trình phù hợp và phân bổ nguồn lực kịp thời để tránh chậm trễ các hạng mục bàn giao.
Các điều chỉnh khác có thể thực hiện
Chúng ta có thể bổ sung thêm chi tiết cho biểu đồ Gantt bằng matplotlib. Ví dụ:
Thêm tỷ lệ phần trăm hoàn thành trên mỗi thanh.
Chia nhỏ một số nhiệm vụ thành các phân nhiệm (chúng ta đã bàn cách thực hiện ở phần trước).
Chú thích các nhiệm vụ có liên quan.
Đánh dấu các cột mốc và thời hạn quan trọng.
Làm nổi bật cuối tuần và ngày nghỉ.
Sắp xếp các thanh theo nhóm hoặc loại nhiệm vụ.
Thêm các tick phụ trên trục x để tăng độ chi tiết thông tin.
Cải thiện định dạng và bố cục tổng thể của biểu đồ.
Tuy nhiên, điều quan trọng là giữ cho biểu đồ Gantt gọn gàng và tránh chất quá nhiều chi tiết. Cũng như mọi loại trực quan hóa dữ liệu khác, chúng ta cần duy trì cân bằng giữa dung lượng thông tin và khả năng đọc của biểu đồ, cũng như khả năng đọc của mã dùng để tạo biểu đồ đó.
Bắt đầu tự tạo biểu đồ Gantt trong Python với Matplotlib
Tóm lại, trong hướng dẫn này, chúng ta đã khám phá:
biểu đồ Gantt là gì
nó hiển thị kiểu thông tin nào
khi nào được dùng
các cách và lưu ý khi tạo biểu đồ Gantt với matplotlib
cách tạo biểu đồ Gantt trong Python với matplotlib
cách điều chỉnh thêm để biểu đồ giàu thông tin hơn
cách diễn giải kết quả cuối cùng.
Ngoài ra, chúng ta đã xem nhiều ví dụ biểu đồ Gantt và quy trình xây dựng từng bước.
Để có cách tiếp cận tích hợp hơn trong việc học cách tạo các biểu đồ hấp dẫn và nhiều thông tin trong Python, hãy xem lộ trình kỹ năng Data Visualization with Python của chúng tôi.
Trong hướng dẫn từng bước này, chúng ta sẽ bàn về biểu đồ Gantt là gì, vì sao và khi nào kiểu trực quan hóa này hữu ích, cách tạo biểu đồ Gantt trong Python với matplotlib, và cách tùy chỉnh thêm. Trong quá trình đó, chúng ta sẽ xây dựng một số ví dụ biểu đồ Gantt bằng matplotlib.
Biểu đồ Gantt là gì và vì sao nó hữu ích?
Biểu đồ Gantt là một dạng biểu đồ cột dùng để minh họa lịch trình lập kế hoạch và quản lý dự án hoàn chỉnh. Nó thường hiển thị các thông tin như tên nhiệm vụ của dự án, ngày bắt đầu và kết thúc, nhóm phụ trách nhiệm vụ, trạng thái hoàn thành dưới dạng phần trăm hoặc phân số, hiệu suất theo nhóm, và các cột mốc quan trọng của dự án.
Tên nhiệm vụ được sắp xếp dọc theo trục y của biểu đồ Gantt, thường được sắp theo thứ tự thời gian của ngày bắt đầu từ trên xuống dưới. Trục x dùng để hiển thị các khoảng thời gian, với độ rộng của mỗi thanh tương ứng với thời lượng thực hiện của từng nhiệm vụ.
Vì biểu đồ Gantt về bản chất là một dạng cụ thể của biểu đồ cột ngang, ta có thể tạo nó trong nhiều thư viện trực quan hóa dữ liệu của Python, gồm matplotlib, Plotly, Bokeh và Altair. Trong hướng dẫn này, chúng ta sẽ tập trung vào việc tạo biểu đồ Gantt trong thư viện phổ biến nhất – matplotlib.
Nếu bạn muốn khám phá các cách thay thế để tạo biểu đồ Gantt và các loại biểu đồ khác trong Python, hãy tham khảo khóa học Introduction to Data Visualization with Plotly in Python. Nếu bạn cần ôn lại hoặc nâng cao kỹ năng matplotlib, các khóa học này sẽ hữu ích: Introduction to Data Visualization with Matplotlib và Python for MATLAB Users.
Cách tạo biểu đồ Gantt trong Python với Matplotlib
Sử dụng barh()
Bắt đầu với việc dựng một biểu đồ Gantt cơ bản bằng matplotlib sử dụng phương thức
barh()củamatplotlib.pyplot.Trước hết, ta cần tải các thư viện cần thiết:
Bước tiếp theo là tạo dữ liệu giả để thực hành:
Kết quả:
Để thuận tiện cho việc dựng biểu đồ Gantt cho dữ liệu này, chúng ta cần tính thêm bốn cột đại diện cho các thông tin sau:
Hãy kiểm tra kết quả thu được:
Kết quả:
Bây giờ, chúng ta sẵn sàng tạo một biểu đồ Gantt cơ bản trong matplotlib:
Kết quả:
Biểu đồ trên cần khá nhiều điều chỉnh để chúng ta có thể rút trích tối đa thông tin từ đó:
Chúng ta sẽ sớm triển khai tất cả những tinh chỉnh đó. Tuy nhiên, trước khi làm vậy, hãy xem cách xử lý việc tạo biểu đồ Gantt cơ bản.
Sử dụng
broken_barh()Khi một số nhiệm vụ có hai hoặc nhiều phân nhiệm trải dài theo thời gian, chúng ta nên dùng một phương thức khác của matplotlib –
broken_barh().Để có dữ liệu giả để thử cách tiếp cận này, hãy làm như sau:
completion_frac).startvàendthànhstart_1vàend_1tương ứng (cho tiện).Kết quả:
Lưu ý rằng giờ đây nhiệm vụ D có hai phân nhiệm, nhiệm vụ H có ba phân nhiệm, còn C và K mỗi nhiệm vụ có một phân nhiệm. Vì vậy, D và H là những nhiệm vụ mà chúng ta sẽ áp dụng phương thức
broken_barh(). Do cú pháp của phương thức này kém trực quan hơnbarh(), hãy xem các tham số chính và định dạng của chúng. Các tham số bắt buộc củabroken_barh()là:xranges– một dãy các bộ giá trị theo định dạng (xmin,xwidth) để chỉ điểm bắt đầu và độ dài của mỗi thanh. Tại đây, mỗi thanh đại diện cho một phân nhiệm. Vậy tham số này hiển thị ngày bắt đầu và thời lượng của mỗi phân nhiệm.yrange– một bộ giá trị theo định dạng (ymin,yheight) để chỉ vị trí y và chiều cao cho mỗi thanh.Bây giờ, hãy vẽ biểu đồ Gantt "gãy đoạn" của chúng ta. Thuật toán như sau:
barh()như trước.broken_barh().broken_barh().Kết quả:
Trong đoạn mã trên, thực ra chúng ta có thể dùng phương thức
broken_barh()để vẽ các thanh cả cho những nhiệm vụ chỉ có một phân nhiệm. Khi đó, cần thay dòng:bằng dòng này:
Cách này cũng giúp mã của chúng ta đồng nhất và dễ đọc hơn.
Cách tùy chỉnh biểu đồ Gantt trong Matplotlib
Quay lại dataframe ban đầu của chúng ta:
Kết quả:
và biểu đồ Gantt đầu tiên của chúng ta:
Kết quả:
Cụ thể, chúng ta muốn thêm một số tùy chỉnh vào biểu đồ này để nó giàu thông tin hơn.
Để đào sâu hơn vào việc tùy chỉnh biểu đồ với matplotlib, hãy tham khảo các tài nguyên sau: Matplotlib Tutorial: Python Plotting và Matplotlib Cheat Sheet: Plotting in Python.
Các điều chỉnh cơ bản cho biểu đồ Gantt
Gồm có:
Thêm tiêu đề biểu đồ
Có tiêu đề ý nghĩa là điều bắt buộc với bất kỳ biểu đồ nào, kể cả biểu đồ Gantt. Giả sử dự án của chúng ta tên là Project X:
Kết quả:
Điều chỉnh và tùy biến các trục và thêm lưới
Ở bước này, chúng ta sẽ xây dựng tiếp trên đoạn mã trước và thực hiện các thao tác sau:
ax.Kết quả:
Nếu bạn cần thực hành Python nhiều hơn để viết và đọc mã Python dễ dàng, khóa học Intermediate Python của chúng tôi là điểm tham chiếu tốt.
Tô màu nhiệm vụ theo nhóm
Bây giờ, hãy mã hóa màu cho mỗi thanh (đại diện cho một nhiệm vụ cụ thể) theo nhóm phụ trách nhiệm vụ đó. Để làm vậy, chúng ta sẽ:
Kết quả:
Thêm chú giải
Một điều còn thiếu trong ví dụ biểu đồ Gantt trên là chú giải thể hiện màu nào ứng với nhóm nào. Để khắc phục, hãy tạo các patch – đối tượng đồ họa 2D của matplotlib được tô bằng một màu xác định trước. Chúng ta sẽ dùng lớp matplotlib.patches.Patch để tạo danh sách patch, mỗi nhóm một patch, tô màu tương ứng:
Giờ chúng ta sẵn sàng thêm chú giải vào biểu đồ:
Kết quả:
Ví dụ biểu đồ Gantt trên trông nhiều thông tin hơn hẳn.
Bạn sẽ tìm thấy thêm nhiều kỹ thuật để cải thiện thẩm mỹ và khả năng đọc của biểu đồ trong khóa học Improving Your Data Visualizations in Python.
Thêm trạng thái hoàn thành
Cho đến giờ, chúng ta vẫn chưa dùng cột
completion_daysđã tính ở đầu hướng dẫn. Bây giờ, chúng ta sẽ dùng nó để làm cho biểu đồ Gantt mang nhiều thông tin hơn bằng cách hiển thị giai đoạn hoàn thành của mỗi nhiệm vụ.Về kỹ thuật, chúng ta sẽ thêm một thanh nữa chồng lên mỗi thanh đã vẽ. Thanh dưới biểu diễn tổng thời lượng của mỗi nhiệm vụ theo số ngày được phân bổ, trong khi thanh trên biểu diễn trạng thái hoàn thành của nhiệm vụ đó theo số ngày được phân bổ.
Với mỗi nhiệm vụ, cả hai thanh sẽ có cùng một màu theo nhóm tương ứng, nhưng thanh dưới sẽ nhạt màu hơn thanh trên để dễ phân biệt.
Nói cách khác, nếu một nhóm đang vượt tiến độ ở một nhiệm vụ, sự kết hợp của hai thanh sẽ cho thấy như thể nhóm đã làm nhiều ngày cho nhiệm vụ đó hơn dự kiến (nghĩa là nhiệm vụ có khả năng hoàn thành trước hạn).
Ở chiều ngược lại, nếu một nhóm đang chậm tiến độ ở một nhiệm vụ, sự kết hợp các thanh tương ứng sẽ cho thấy như thể nhóm làm ít ngày hơn dự kiến (nghĩa là nhiệm vụ có khả năng hoàn thành sau hạn).
Kết quả:
Từ biểu đồ trên, ta thấy các nhóm không có cùng nhịp độ hoàn thành nhiệm vụ, điều khá phổ biến trong nhiều dự án thực tế. Để rút thêm thông tin, giả sử ngày hiện tại là 17/11/2022 và đánh dấu ngày này trên biểu đồ:
Kết quả:
Chúng ta có thể đưa ra các nhận xét sau về trạng thái hiện tại của Project X:
Những nhận xét như vậy có thể giúp các trưởng nhóm và quản lý dự án điều chỉnh lịch trình phù hợp và phân bổ nguồn lực kịp thời để tránh chậm trễ các hạng mục bàn giao.
Các điều chỉnh khác có thể thực hiện
Chúng ta có thể bổ sung thêm chi tiết cho biểu đồ Gantt bằng matplotlib. Ví dụ:
Tuy nhiên, điều quan trọng là giữ cho biểu đồ Gantt gọn gàng và tránh chất quá nhiều chi tiết. Cũng như mọi loại trực quan hóa dữ liệu khác, chúng ta cần duy trì cân bằng giữa dung lượng thông tin và khả năng đọc của biểu đồ, cũng như khả năng đọc của mã dùng để tạo biểu đồ đó.
Bắt đầu tự tạo biểu đồ Gantt trong Python với Matplotlib
Tóm lại, trong hướng dẫn này, chúng ta đã khám phá:
Ngoài ra, chúng ta đã xem nhiều ví dụ biểu đồ Gantt và quy trình xây dựng từng bước.
Để có cách tiếp cận tích hợp hơn trong việc học cách tạo các biểu đồ hấp dẫn và nhiều thông tin trong Python, hãy xem lộ trình kỹ năng Data Visualization with Python của chúng tôi.