Xem thêm

Vẽ đồ thị trong Python với thư viện Matplotlib

Huy Erick
Trước khi chúng ta đi vào câu hỏi "Tại sao Matplotlib là một thư viện phổ biến trong Python?", hãy nhớ lại một câu nói của người xưa mà vẫn có giá trị cho tới...

Trước khi chúng ta đi vào câu hỏi "Tại sao Matplotlib là một thư viện phổ biến trong Python?", hãy nhớ lại một câu nói của người xưa mà vẫn có giá trị cho tới ngày nay.

"Một bức tranh hơn ngàn lời nói." - Ngạn ngữ Anh

Python là ngôn ngữ được sử dụng phổ biến trong lĩnh vực phân tích dữ liệu. Trong khoa học dữ liệu, việc trực quan hóa thông qua các đồ thị và biểu đồ giúp chúng ta hiểu các mối quan hệ trong dữ liệu một cách dễ dàng hơn. Vì vậy, thư viện Matplotlib là một trong những thư viện được sử dụng rộng rãi trong Python.

Hãy tưởng tượng bạn có một tập tin dữ liệu khổng lồ khoảng 20MB. Khi biểu diễn dữ liệu này dưới dạng đồ thị, bạn sẽ cảm thấy hứng khởi vì bạn có thể hiểu ngay lập tức những thông tin mà 20MB đó muốn truyền tải. Ngày nay, khi Big data trở thành một thực tế, hàng ngày có rất nhiều dữ liệu được tạo ra. Việc trực quan hóa dữ liệu ngày càng trở nên cần thiết và thúc đẩy sự phát triển của các thư viện như Matplotlib.

Mục đích của bài viết này là giúp bạn hiểu cách vẽ các đồ thị và biểu đồ với thư viện Matplotlib. Từ đó, bạn có thể sử dụng nó một cách thành thạo để trực quan hóa dữ liệu của mình.

John D. Hunter, một nhà thần kinh học, bắt đầu phát triển Matplotlib vào năm 2003 để mô phỏng các tập lệnh MATLAB. Ông qua đời vào năm 2012 ở tuổi 44. Hiện nay, Matplotlib được phát triển và duy trì bởi cộng đồng các nhà phát triển khác.

Trong MATLAB, chúng ta không cần import bất cứ thứ gì và có thể sử dụng các hàm có sẵn ngay lập tức. Tuy nhiên, trong Python, chúng ta phải import các thư viện cần thiết. Matplotlib có nguồn gốc từ MATLAB, do đó module Pylab trong thư viện Matplotlib được xây dựng để cung cấp cách sử dụng hàm tương tự như MATLAB. Nó bao gồm một số hàm và lớp từ Numpy và Matplotlib vào namespace, giúp người dùng MATLAB chuyển đổi sang Python một cách dễ dàng.

Khi bạn import lệnh sau vào Python:

from pylab import *

Bạn có thể sử dụng ngay các hàm như plot() và array() giống như trong MATLAB. Tuy nhiên, lệnh import này không được ổn định và có thể gây xung đột với các module khác trong chương trình Python. Pylab để lại lịch sử không tốt và không được khuyến nghị sử dụng. Thay vào đó, chúng ta nên sử dụng Matplotlib.

Trong Pylab, có rất nhiều các import tiền ẩn có khả năng xung đột. Matplotlib đã từ bỏ module này và khuyến nghị không nên sử dụng Pylab, để mọi thứ trở nên rõ ràng hơn. Một cách chính xác để thay thế lệnh import này là:

import matplotlib.pyplot as plt

Nếu bạn đã đọc tài liệu về Matplotlib, bạn sẽ thấy dòng code sau là một phân cấp với các đối tượng Python lồng vào nhau. Phân cấp ở đây nghĩa là kiểu cấu trúc cây các đối tượng Matplotlib trả về từ hàm plot(). Đối tượng Figure là nơi chứa đồ họa trong Matplotlib, nó có thể chứa các đối tượng Axes. Dưới Axes là một hệ thống các đối tượng nhỏ hơn như các đường thẳng, các hộp văn bản... Hầu hết các phần tử của đồ thị đều có thể tương tác như các đối tượng trong Python.

plt.plot([1, 2, 3])

Ví dụ:

fig, _ = plt.subplots()
type(fig) # 

Trong đoạn code trên, chúng ta tạo ra hai biến với hàm plt.subplots(), biến đầu tiên là fig chứa đối tượng Figure, biến thứ hai _ chứa các đối tượng khác. Đây là một cấu trúc Tuple trong Python, vì plt.subplots() trả về kiểu Tuple. Do cấu trúc cây phân cấp, chúng ta có thể truy cập đến phần tử được đánh dấu, ví dụ:

one_tick = fig.axes[0].yaxis.get_major_ticks()[0]
type(one_tick) # 

Biến fig là một thể hiện của lớp Figure và chứa nhiều đối tượng Axes bên trong. Mỗi Axes có một yaxis và xaxis và chúng chứa một tập các major_sticks và chúng ta lấy phần tử đầu tiên.

Một ví dụ khác từ Matplotlib để hiểu rõ hơn về phân cấp đối tượng trong Matplotlib.

Vẽ đồ thị trong Python với thư viện Matplotlib

Hình ảnh trên được tạo ra từ đoạn code sau, bạn có thể tham khảo tại Matplotlib.

Khi sử dụng module pylot trong thư viện Matplotlib, chúng ta sẽ import nó với tên ngắn gọn là plt. %matplotlib inline là câu lệnh của Jupyter Notebook để vẽ các đồ thị bên trong cell của Jupyter Notebook.

Để vẽ một dạng đồ thị, chúng ta cần xem đối tượng plt có những phương thức nào, bạn có thể sử dụng:

dir(plt)

Câu lệnh plt.plot() sẽ vẽ một đồ thị bằng cách nối các điểm bằng đường thẳng (đối tượng matplotlib.lines.Line2D). Trong ví dụ này, chúng ta đưa vào một List các số và Matplotlib sẽ vẽ ra đồ thị bằng cách nối các điểm. Vì plt.plot() trả về một đối tượng, do đó khi muốn hiển thị đồ thị, chúng ta cần gọi plt.show().

Phương thức plot() có 3 tham số:

plot(x, y, format)
  • Tham số x là một danh sách các tọa độ trục x.
  • Tham số y là một danh sách các tọa độ trục y.
  • Tham số format là định dạng đồ thị.

Trong ví dụ đầu tiên, khi chúng ta đưa vào một List, mặc định đó là danh sách tọa độ trục y và định dạng mặc định là vẽ đường thẳng giữa các điểm. Ví dụ trên tương đương với:

plt.plot([1,2,3,4,10])

Kết quả sau khi sử dụng plt.show():

Kết quả đồ thị

Chú ý, trong bài viết này tôi sẽ sử dụng Jupyter Notebook để demo các ví dụ. Nếu bạn chưa biết cài đặt và sử dụng Jupyter Notebook, bạn có thể tham khảo:

Quay lại với phần định dạng đồ thị trong tham số thứ 3 của phương thức plot(). Định dạng này được viết tắt dưới dạng tổ hợp của ba thành phần {color}{marker}{line}. Ví dụ "go-" sẽ cho định dạng điểm có màu xanh và nối hai điểm bằng đường thẳng. Chúng ta thử thực hiện nó:

plt.plot([1,2,3,4,10], 'go-')

Chúng ta cũng có một số định dạng khác như sau:

  • 'r*- các điểm là hình ngôi sao màu đỏ, đường nối các điểm dạng -.
  • 'bD-.' các điểm là hình kim cương màu xanh dương, đường nối các điểm dạng -.
  • 'g^- các điểm là hình tam giác hướng lên màu xanh lá, đường nối các điểm dạng -.
  • Nếu bạn không muốn các điểm được nối với nhau, bạn có thể loại bỏ định dạng đường thẳng, ví dụ 'go-' trở thành 'go'

2.2 Vẽ nhiều tập điểm phân tán trên cùng đồ thị

Bạn có thể vẽ nhiều tập điểm phân tán trên cùng một đồ thị bằng cách gọi phương thức plot() nhiều lần. Ví dụ dưới đây sẽ vẽ hai đường đồ thị dựa trên hai tập điểm khác nhau với định dạng khác nhau:

plt.plot([0,1,2,3,4], [1,2,3,4,10], 'go-', label='Python')
plt.plot([0,1,2,3,4], [10,4,3,2,1], 'ro-', label='C#')
plt.plot([2.5,2.5,2.5,1.5,0.5], [1,3,5,7,10], 'bo-', label='Java')
plt.title('Vẽ đồ thị trong Python với Matplotlib')
plt.xlabel('X')
plt.ylabel('Y')
plt.legend(loc='best')
plt.show()

Trong ví dụ này, chúng ta có thêm một số điểm cần chú ý:

  • Thêm nhãn cho từng tập điểm với tham số thứ 4 trong plot().
  • Hiển thị ghi chú các thành phần trong đồ thị với phương thức legend().
  • Hiển thị nhãn các trục tọa độ x, y với xlabel()ylabel().
  • Để giới hạn giá trị trục x và y, chúng ta dùng xlim()ylim().

2.3 Vẽ nhiều đồ thị trong cùng một ảnh

Phần đầu bài viết chúng ta đã biết về phân cấp đối tượng trong Matplotlib. Mỗi plt.plot() trả về một đối tượng Figure (là hình ảnh bên ngoài), trong Figure này có rất nhiều các đối tượng Axes (đồ thị con bên trong). Trong phần này, chúng ta sẽ vẽ hai đồ thị cạnh nhau nằm trong cùng một Figure (hình ảnh).

fig, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(10,4), sharey=True, dpi=120)
ax1.plot([0,1,2,3,4], [1,2,3,4,10], 'go-')
ax2.plot([0,1,2,3,4], [10,4,3,2,1], 'ro-')
ax3.plot([2.5,2.5,2.5,1.5,0.5], [1,3,5,7,10], 'bo-')

# Title, X and Y labels, X and Y Lim
ax1.set_title('Python')
ax2.set_title('C#')
ax3.set_title('Java')

ax1.set_xlabel('X')
ax2.set_xlabel('X')
ax3.set_xlabel('X')

ax1.set_ylabel('Y')
ax2.set_ylabel('Y')
ax3.set_ylabel('Y')

ax1.set_xlim(0, 6)
ax2.set_xlim(0, 6)
ax3.set_xlim(0, 6)

ax1.set_ylim(0, 12)
ax2.set_ylim(0, 12)
ax3.set_ylim(0, 12)

plt.tight_layout()
plt.show()

Sự khác biệt giữa plot()scatter():

  • plot() không có khả năng thay đổi màu và kích thước điểm trong tập hợp điểm ban đầu, trong khi scatter() có thể.
  • plot() có thể vẽ các đường nối hai điểm liên tiếp, scatter() thì không.

Ví dụ dưới đây vẽ ra các điểm trên đồ thị với dữ liệu về chiều cao và cân nặng. Mỗi điểm có màu ngẫu nhiên và kích thước cũng ngẫu nhiên.

height = np.array([167,170,149,165,155,180,166,146,159,185,145,168,172,181,169])
weight = np.array([86,74,66,78,68,79,90,73,70,88,66,84,67,84,77])
colors = np.random.rand(15)
area = (30 * np.random.rand(15))**2

plt.xlim(140,200)
plt.ylim(60,100)
plt.scatter(height,weight,s=area,c=colors)
plt.title("Chiều cao và cân nặng")
plt.xlabel("Chiều cao - cm")
plt.ylabel("Cân nặng - kg")
plt.show()

Kết quả:

Vẽ tập hợp điểm phân tán

Bài viết gốc được đăng tải tại allaravel.com

Có thể bạn quan tâm:

  • Thuật toán Gradient Descent
  • [Python cơ bản thường dùng trong công việc] Phần 13 : Restful client
  • [Python cơ bản thường dùng trong công việc] Phần 2 : Cú pháp thông dụng

Xem thêm tuyển dụng IT ở Hà Nội, Đà Nẵng, HCM hấp dẫn trên TopDev.

1