Hướng dẫn dùng matplotlib size python

Chúng ta đã đưa ra rất nhiều ví dụ để vẽ đồ thị trong các chương trước của hướng dẫn Python trên Matplotlib. Một câu hỏi thường gặp là làm thế nào để có nhiều plots trong một đồ thị?

Trong trường hợp đơn giản nhất điều này có thể có nghĩa là, bạn có một đường cong và bạn muốn một đường cong in qua nó. Đây không phải là một vấn đề, bởi vì nó sẽ đủ để đưa haiplots trong kịch bản của bạn, như chúng ta đã thấy trước đây. Trường hợp thú vị hơn là, nếu bạn muốn hai plots trong một cửa sổ. Trong một cửa sổ có nghĩa là chúng phải ở hai vị trí con riêng lẻ, nghĩa là không được in trên nhau. Ý tưởng là có nhiều hơn một đồ thị trong một cửa sổ và mỗi đồ thị xuất hiện trong subplot riêng của mình.

Chúng tôi sẽ trình bày hai cách khác nhau để hoàn thành mục tiêu này:

    subplot
    gridspec

Chúng tôi nghĩ rằng gridspec là lựa chọn tốt nhất vì nó dễ sử dụng hơn rất nhiều, nếu bố cục phức tạp hơn!

Subplot: Làm việc với nhiều figures và axes

Cú pháp: subplot(nrows, ncols, plot_number)

Nếu một subplot được áp dụng cho một con số, con số này sẽ được chia thành các trục con 'nrows' * 'ncols'. Tham số 'plot_number' xác định subplot mà hàm phải tạo ra. 'plot_number' có thể dao động từ 1 đến tối đa là 'nrows' * 'ncols'.

Nếu các giá trị của ba tham số nhỏ hơn 10, thì hàm subplot có thể được gọi với một tham số int, trong đó hàng trăm đại diện cho 'nrows', hàng chục đại diện cho 'ncols' vàhàng đơn vị biểu diễn 'plot_number'. Điều này có nghĩa là: Thay vì subplot (2, 3, 4) chúng ta có thể viết subplot (234).

Ví dụ sau đây tạo ra hai subplot của lưới 2x2

>>> import matplotlib.pyplot as plt

>>> python_course_green = "#476042"

>>> plt.figure(figsize=(6, 4))

<matplotlib.figure.Figure object at 0x0000000003E7D710>

>>> plt.subplot(221) # equivalent to: plt.subplot(2, 2, 1)

<matplotlib.axes._subplots.AxesSubplot object at 0x0000000003E7D7B8>

>>> plt.text(0.5, # x coordinate, 0 leftmost positioned, 1 rightmost

...          0.5, # y coordinate, 0 topmost positioned, 1 bottommost

...          'subplot(2,2,1)', # the text which will be printed

...          horizontalalignment='center', # shortcut 'ha'

...          verticalalignment='center', # shortcut 'va'

...          fontsize=20, # can be named 'font' as well

...          alpha=.5 # float (0.0 transparent through 1.0 opaque)

...          )

<matplotlib.text.Text object at 0x0000000004B0E080>

>>> plt.subplot(224, axisbg=python_course_green)

C:\ProgramData\Anaconda2\lib\site-packages\matplotlib\cbook.py:136: MatplotlibDeprecationWarning: The axisbg attribute was deprecated in version 2.0. Use facecolor instead.

  warnings.warn(message, mplDeprecation, stacklevel=1)

<matplotlib.axes._subplots.AxesSubplot object at 0x0000000004EDA9E8>

>>> plt.text(0.5, 0.5,

...          'subplot(2,2,4)',

...          ha='center', va='center',

...          fontsize=20,

...          color="y")

<matplotlib.text.Text object at 0x0000000004B0E4A8>

>>> plt.show()

>>>

Hướng dẫn dùng matplotlib size python

Mặc dù cách tiếp cận trước đó có thể chấp nhận được, nhưng theo tiếp cận hướng đối tượng bằng cách sử dụng các thể hiện của lớp figure. Chúng tôi chứng minh điều này bằng cách viết lại ví dụ trước. Trong trường hợp này, chúng ta phải sử dụng phương thức "add_subplot" cho đối tượng figure.

>>> import matplotlib.pyplot as plt

>>> python_course_green = "#476042"

>>> fig = plt.figure(figsize=(6, 4))

>>> sub1 = fig.add_subplot(221) # equivalent to: plt.subplot(2, 2, 1)

>>> sub1.text(0.5, # x coordinate, 0 leftmost positioned, 1 rightmost

...           0.5, # y coordinate, 0 topmost positioned, 1 bottommost

...           'subplot(2,2,1)', # the text which will be printed

...           horizontalalignment='center', # shortcut 'ha'

...           verticalalignment='center', # shortcut 'va'

...           fontsize=20, # can be named 'font' as well

...           alpha=.5 # float (0.0 transparent through 1.0 opaque)

...           )

<matplotlib.text.Text object at 0x0000000005A342B0>

>>> sub2 = fig.add_subplot(224, axisbg=python_course_green)

>>> sub2.text(0.5, 0.5,

...           'subplot(2,2,4)',

...           ha='center', va='center',

...           fontsize=20,

...           color="y")

<matplotlib.text.Text object at 0x0000000005BFBEB8>

>>> plt.show()

>>>

Để loại bỏ, hay tùy biến ticks trong các subplot, với cách tiếp cận đầu tiên ta có thể sử dụng phương thức xticks,yticks() của lớp pyplot, tuy nhiên cách sử dụng OOP ở ví dụ thứ hai ta cần sử dụng phương thức set_xticks(), và set_yticks() của lớp Axes trả về từ phương thức add_subplot(). Các bạn tự thực hành phần này nhé.

Các bạn đoán thử xem làm thế nào tôi có thể tạo được một figure với cách bố trí các subplots như sau: (các bạn chú ý phần màu tôi đã trình bầy trong lời giải sẽ giúp các bạn hiểu về cách chia blocks)

Bài 1:

Lời giải tham khảo:

>>> import  matplotlib.pyplot as plt

>>> X = [ (2,1,1), (2,3,4), (2,3,5), (2,3,6) ]

>>> for nrows, ncols, plot_number in X:

...     plt.subplot(nrows, ncols, plot_number)

...

<matplotlib.axes._subplots.AxesSubplot object at 0x0000000005C722E8>

<matplotlib.axes._subplots.AxesSubplot object at 0x000000000DF045C0>

<matplotlib.axes._subplots.AxesSubplot object at 0x000000000E1140B8>

<matplotlib.axes._subplots.AxesSubplot object at 0x000000000E177B38>

>>> plt.show()

Bài 2:

Lời giải tham khảo:

>>> import  matplotlib.pyplot as plt

>>> X = [ (2,3,1),(2,3,2), (2,3,3),(2,1,2)]

>>>

>>> for nrows, ncols, plot_number in X:

...     plt.subplot(nrows, ncols, plot_number)

...

<matplotlib.axes._subplots.AxesSubplot object at 0x000000000586D208>

<matplotlib.axes._subplots.AxesSubplot object at 0x0000000005B39630>

<matplotlib.axes._subplots.AxesSubplot object at 0x0000000005503F98>

<matplotlib.axes._subplots.AxesSubplot object at 0x000000000E94EA58>

>>> plt.show()

>>>

Bài 3:

Lời giải tham khảo:

>>> import  matplotlib.pyplot as plt

>>> X = [  (4,2,1),(4,2,2), (4,2,3), (4,2,5), (4,2,(4,6)), (4,1,4) ]

>>> plt.subplots_adjust(bottom=0.05, left=0.05, top = 0.975, right=0.95)

>>>

>>> for nrows, ncols, plot_number in X:

...     plt.subplot(nrows, ncols, plot_number)

...

<matplotlib.axes._subplots.AxesSubplot object at 0x000000000E95FC88>

<matplotlib.axes._subplots.AxesSubplot object at 0x000000000EB76908>

<matplotlib.axes._subplots.AxesSubplot object at 0x000000000EDE1D68>

<matplotlib.axes._subplots.AxesSubplot object at 0x000000000E443A20>

<matplotlib.axes._subplots.AxesSubplot object at 0x000000000573D3C8>

<matplotlib.axes._subplots.AxesSubplot object at 0x00000000051E4BE0>

>>> plt.show()

Dùng gridspec để vẽ subplots.

'Matplotlib.gridspec' chứa một lớp GridSpec. Nó có thể được sử dụng như là một thay thế cho subplot để xác định hình học của subplots được tạo ra. Ý tưởng cơ bản đằng sau GridSpec là một 'lưới'. Một lưới được thiết lập với số hàng và cột. Chúng ta phải xác định sau này, bao nhiêu lưới mà một subplot nên phủ.

Ví dụ sau cho thấy trường hợp nhỏ hoặc đơn giản nhất, tức là lưới 1x1

>>> import matplotlib.pyplot as plt

>>> from matplotlib.gridspec import GridSpec

>>> fig = plt.figure()

>>> gs = GridSpec(1, 1)

>>> ax = fig.add_subplot(gs[0,0])

>>> plt.show()

>>>

Chúng ta có thể sử dụng một số thông số của Gridspec, ví dụ: Chúng ta có thể xác định rằng biểu đồ của chúng ta sẽ bắt đầu ở mức 20% từ đáy và 15% ở phía bên trái của vùng hình có sẵn:

>>> import matplotlib.pyplot as plt

>>> from matplotlib.gridspec import GridSpec

>>> fig = plt.figure()

>>> gs = GridSpec(1, 1,

...               bottom=0.2,

...               left=0.15,

...               top=0.8)

>>> ax = fig.add_subplot(gs[0,0])

>>> plt.show()

 

Ví dụ tiếp theo cho thấy một thiết kế lưới phức tạp hơn:

>>> import matplotlib.gridspec as gridspec

>>> import matplotlib.pyplot as pl

>>> pl.figure(figsize=(6, 4))

<matplotlib.figure.Figure object at 0x000000000E1D9278>

>>> G = gridspec.GridSpec(3, 3)

>>> axes_1 = pl.subplot(G[0, :])

>>> pl.text(0.5, 0.5, 'Axes 1', ha='center', va='center', size=24, alpha=.5)

<matplotlib.text.Text object at 0x000000000E371358>

>>> axes_2 = pl.subplot(G[1, :-1])

>>> pl.text(0.5, 0.5, 'Axes 2', ha='center', va='center', size=24, alpha=.5)

<matplotlib.text.Text object at 0x000000000E9FEE48>

>>> axes_3 = pl.subplot(G[1:, -1])

>>> pl.text(0.5, 0.5, 'Axes 3', ha='center', va='center', size=24, alpha=.5)

<matplotlib.text.Text object at 0x000000000E698E80>

>>> axes_4 = pl.subplot(G[-1, 0])

>>> pl.text(0.5, 0.5, 'Axes 4', ha='center', va='center', size=24, alpha=.5)

<matplotlib.text.Text object at 0x000000000E698908>

>>> axes_5 = pl.subplot(G[-1, -2])

>>> pl.text(0.5, 0.5, 'Axes 5', ha='center', va='center', size=24, alpha=.5)

<matplotlib.text.Text object at 0x000000000E5D6240>

>>> pl.tight_layout()

>>> pl.show()

Bài tập hãy tạo ra một figure có các subplot theo hình sau:

Lời giải:

>>> import matplotlib.gridspec as gridspec

>>> import matplotlib.pyplot as pl

>>> pl.figure(figsize=(6, 4))

<matplotlib.figure.Figure object at 0x000000000E45A2B0>

>>> G = gridspec.GridSpec(3, 3)

>>> axes_1 = pl.subplot(G[0, :])

>>> axes_2 = pl.subplot(G[1:,0])

>>> axes_3 = pl.subplot(G[1, 1:])

>>> axes_4 = pl.subplot(G[-1, 1:])

>>> pl.tight_layout()

>>> pl.show()

Bạn nhận thấy lời giải khi sử dụng gridspec dễ hiểu hơn đúng không!

Vẽ một plot bên trong một plot khác.

Ta dùng add_axes(*args, **kwargs) của lớp figure.
Thêm một trục tại vị trí rect [trái, dưới, chiều rộng, chiều cao] nơi mà tất cả các số lượng nằm trong các phân số của chiều rộng và chiều cao. 
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> fig = plt.figure()
>>> X = [1, 2, 3, 4, 5, 6, 7]
>>> Y = [1, 3, 4, 2, 5, 8, 6]
>>> axes1 = fig.add_axes([0.1, 0.1, 0.9, 0.9]) # main axes
>>> axes2 = fig.add_axes([0.2, 0.6, 0.4, 0.3]) # inset axes
>>> # main figure
... axes1.plot(X, Y, 'r')
[<matplotlib.lines.Line2D object at 0x000000000ED4CA58>]
>>> axes1.set_xlabel('x')
<matplotlib.text.Text object at 0x00000000051B3978>
>>> axes1.set_ylabel('y')
<matplotlib.text.Text object at 0x000000000E8C3978>
>>> axes1.set_title('title')
<matplotlib.text.Text object at 0x00000000051B5E48>
>>> # insert
... axes2.plot(Y, X, 'g')
[<matplotlib.lines.Line2D object at 0x000000000ED4CB38>]
>>> axes2.set_xlabel('y')
<matplotlib.text.Text object at 0x000000000E688CC0>
>>> axes2.set_ylabel('x')
<matplotlib.text.Text object at 0x000000000ED484E0>
>>> axes2.set_title('title inside')
<matplotlib.text.Text object at 0x000000000E96A470>
>>>
>>> plt.show()
>>>
 

 Có thể định cấu hình các dãy của các trục. Điều này có thể được thực hiện bằng cách sử dụng phương thức set_ylim() và set_xlim() trong đối Axis. 

>>> import numpy as np

>>> import matplotlib.pyplot as plt

>>> fig, axes = plt.subplots(1, 3, figsize=(10, 4))

>>> x = np.arange(0, 5, 0.25)

>>> axes[0].plot(x, x**2, x, x**3)

[<matplotlib.lines.Line2D object at 0x000000000EA99400>, <matplotlib.lines.Line2D object at 0x000000000E9547F0>]

>>> axes[0].set_title("default axes ranges")

<matplotlib.text.Text object at 0x000000000EC99358>

>>> axes[1].plot(x, x**2, x, x**3)

[<matplotlib.lines.Line2D object at 0x000000000E954DD8>, <matplotlib.lines.Line2D object at 0x000000000E114400>]

>>> axes[1].axis('tight')

(-0.23750000000000002, 4.9874999999999998, -5.3585937500000007, 112.53046875)

>>> axes[1].set_title("tight axes")

<matplotlib.text.Text object at 0x000000000E8D24E0>

>>> axes[2].plot(x, x**2, x, x**3)

[<matplotlib.lines.Line2D object at 0x000000000E114978>, <matplotlib.lines.Line2D object at 0x000000000E114F98>]

>>> axes[2].set_ylim(0, 60)

(0, 60)

>>> axes[2].set_xlim(2, 5)

(2, 5)

>>> axes[2].set_title("custom axes range");

<matplotlib.text.Text object at 0x000000000587BDA0>

>>> plt.show()

Kết Luận

Qua bài học bạn có thể chia hình vẽ thành nhiều cửa sổ con theo một layout mà bạn muốn qua hai cách subplot và gridspec, theo cảm nhận riêng của cá nhân thì gridspec giúp việc này dễ dàng hơn đặc biệt với trường hợp có layout phức tạp. Trên mỗi một cửa sổ (subplot) bạn có thể tương tác qua đối tượng Axis được trả về khi sử dụng subplot và Gridspec.