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

Bài viết được sự cho phép của tác giả Kien Dang Chung

Trước khi bắt đầu với câu hỏi Tại sao Matplotlib là một thư viện phổ biến trong Python? chúng ta đến với vài câu nói đúc kết của người xưa mà còn nguyên giá trị đến nay.

A picture is worth a thousand words – Một bức tranh hơn ngàn lời nói

Ngạn ngữ Anh

Như chúng ta đã biết Python được sử dụng nhiều nhất trong lĩnh vực phân tích dữ liệu, mà trong khoa học dữ liệu, việc trực quan hóa thông qua các đồ thị, biểu đồ giúp cho chúng ta hiểu được các mối quan hệ trong dữ liệu dễ dàng hơn rất nhiều. Matplotlib là một thư viện sử dụng để vẽ các đồ thị trong Python, chính vì vậy nó là thư viện cực phổ biến của Python. Bạn thử tưởng tượng một file dữ liệu khoảng 20MB, khi vẽ ra đồ thị từ dữ liệu này bạn sướng như phát điên vì có thể hiểu được ngay 20MB đó nói lên cái gì? Ngày nay, khi Big data đang trở thành thực tế, hàng ngày có quá nhiều dữ liệu, việc trực quan hóa dữ liệu càng trở nên cấp thiết và càng thúc đẩy những thư viện như Matplotlib phát triển hơn.

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

Tìm việc làm python lương cao các vị trí cho bạn

PyLab – Matplotib Cơ Bản

Matplotlib là một thư viện vẽ đồ thị trong Python, cho phép bạn tạo ra các biểu đồ và hình ảnh chất lượng cao. PyLab là một mô-đun trong Matplotlib, cung cấp một giao diện giống như Matlab để làm việc với các biểu đồ một cách dễ dàng.

John D. Hunter, một nhà thần kinh học bắt đầu phát triển matplotlib năm 2003 để mô phỏng các tập lệnh MATLAB, ông qua đời năm 2012 ở tuổi 44. Matplotlib giờ đượ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 gì mà có thể sử dụng các hàm có sẵn ngay lập tức khác với Python phải thực hiện 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 để có được cách thức sử dụng hàm như MATLAB. Nó đưa một số hàm và lớp từ Numpy và Matplotlib vào namespace giúp cho người dùng MATLAB có thể chuyển đổi sang Python sử dụng dễ dàng.

Khi bạn thực hiện lệnh import sau vào Python:

from pylab import *

Bạn có thể sử dụng ược ngay các hàm như plot(), array() như trong MATLAB. Vấn đề là với câu lệnh import này không ổn, nó bị chồng chéo các module sử dụng trong chương trình Python. Pylab do lịch sử để lại và nó không được khuyến cáo sử dụng, nó sử dụng các tên vô tội vạ với các chức năng ẩn giấu bên trong và rất khó để kiểm tra lỗi, do đó nên sử dụng Matplotlib.

Trong Pylab có rất nhiều các import tiền ẩn khả năng xung đột được che đậy kín. Matplotlib đã từ bỏ module này và khuyến cáo không nên sử dụng Pylab, mang mọi thứ trở nên rõ ràng hơn là để ngầm định. Không có pylab, chúng ta thường sử dụng một câu lệnh thay thế một cách chính tắc:

import matplotlib.pyplot as plt

Phân cấp đối tượng trong Matplotlib

Nếu bạn đã đọc tài liệu của Matplotlib, dòng code dưới đây 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ừ plot(). Đối tượng Figure là nơi chứa đồ họa Matplotlib, nó có thể chứa các đối tượng Axes. Dưới Axes là hệ thống phân cấp các đối tượng nhỏ hơn như các đường thẳng, các textbox… Hầu hết các phần tử của đồ thị đều có thể tương tác như đối tượng trong Python.

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

Ví dụ:

>>> fig, _ = plt.subplots()
>>> type(fig)
<class 'matplotlib.figure.Figure'>

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

>>> one_tick = fig.axes[0].yaxis.get_major_ticks()[0]
>>> type(one_tick)
<class 'matplotlib.axis.YTick'>

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

Một ví dụ sau đến từ Matplotlib cho chúng ta hiểu 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 sinh ra từ đoạn code sau đây, bạn có thể tham khảo tại Matplotlib.

Vẽ đồ thị với plot()

import matplotlib.pyplot as plt
%matplotlib inline

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

Khi sử dụng module pylot trong thư viện matplotlib chúng ta sẽ import vào với tên ngắn gọn là plt. %matplotlib inline là câu lệnh của Jupyter Notebook để vẽ được 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 (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. Bởi vì plt.plot() trả về một đối tượng, do vậy 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à danh sách các tọa độ trục x
  • Tham số y là danh sách các tọa độ trục y
  • format định dạng đồ thị

Trong ví dụ đầu, khi chúng ta đưa vào một List thì 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ả được đường sau khi sử dụng plt.show():

code python vẽ hình

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, sử dụng Jupyter Notebook 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 ở dạng viết tắt, nó là 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 là đường thẳng. Chúng ta thử thực hiện nó xem sao:

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

  • ‘r*–‘ các điểm hình ngôi sao màu đỏ, đường nối các điểm dạng –.
  • ‘bD-.’ các điểm hình kim cương màu xanh dương, đường nối các điểm dạng -.
  • ‘g^-‘ các điểm 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 nối với nhau, có thể bỏ định dạng đường thẳng đi, ví dụ ‘go-‘ sẽ thành ‘go’

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:

import matplotlib.pyplot as plt

# Vẽ đồ thị
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')

# Đặt tiêu đề và nhãn cho các trục
plt.title('Vẽ đồ thị trong Python với Matplotlib')
plt.xlabel('X')
plt.ylabel('Y')

# Hiển thị chú thích
plt.legend(loc='best')

# Hiển thị đồ thị

thư viện matplotlib

Trong ví dụ này 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() và ylabel().
  10 Lý do nên học Python trong năm 2024
  11 tip học Python dành cho các “newbie”

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 là một đồ 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).

import matplotlib.pyplot as plt

# Tạo các subplot
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(10, 4), sharey=True, dpi=120)

# Vẽ đồ thị cho từng subplot
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-')

# Đặt tiêu đề cho từng đồ thị
ax1.set_title('Python')
ax2.set_title('C#')
ax3.set_title('Java')

# Đặt nhãn cho trục X
ax1.set_xlabel('X')
ax2.set_xlabel('X')
ax3.set_xlabel('X')

# Đặt nhãn cho trục Y
ax1.set_ylabel('Y')
ax2.set_ylabel('Y')
ax3.set_ylabel('Y')

# Đặt giới hạn cho trục X
ax1.set_xlim(0, 6)
ax2.set_xlim(0, 6)
ax3.set_xlim(0, 6)

# Đặt giới hạn cho trục Y
ax1.set_ylim(0, 12)
ax2.set_ylim(0, 12)
ax3.set_ylim(0, 12)

# Căn chỉnh bố cục
plt.tight_layout()

# Hiển thị đồ thị
plt.show()

vẽ đồ thị trong python

Vẽ tập hợp điểm phân tán với scatter()

Sự khác biệt giữa plot() và 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 nhưng scatter() lại 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à có kích thước cũng ngẫu nhiên.

import matplotlib.pyplot as plt
import numpy as np

# Dữ liệu về chiều cao và cân nặng
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])

# Màu sắc và kích thước cho các điểm dữ liệu
colors = np.random.rand(15)
area = (30 * np.random.rand(15)) ** 2

# Đặt giới hạn cho trục x và y
plt.xlim(140, 200)
plt.ylim(60, 100)

# Tạo biểu đồ phân tán
plt.scatter(height, weight, s=area, c=colors)

# Đặt tiêu đề và nhãn trục
plt.title("Chiều cao và cân nặng")
plt.xlabel("Chiều cao - cm")
plt.ylabel("Cân nặng - kg")

# Hiển thị biểu đồ
plt.show()

Kết quả như sau:

vẽ biểu đồ trong python

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

Xem thêm tuyển dụng it hà nội, đà nẵng, hcm hấp dẫn trên TopDev