matplotlib繪圖邏輯(上)

2021-02-21 universebiologygirl
matplotlib繪圖邏輯(上)

matplotlib是一個基於Python的繪圖庫,具有對2D的完全支持和對3D圖形的有限支持,在Python科學計算社區中廣泛使用。

本文對matplotblib的基本繪圖邏輯進行了比較詳細的梳理。寫作過程中參考了很多資料,由於筆記是斷續的,有些可能忘記引用,在此表達感謝。

限於篇幅,本文並不會對一些封裝比較高級的繪圖接口進行介紹。此外,由於繪圖中涉及到的類與接口實在是太多,不可能面面俱到。

有必要提及,Matplotlib的主要開發者John D. Hunter是一名神經生物學家,但2012年不幸因癌症去世,感謝他開發出了一個這麼優秀的庫。

如果你覺得看完本文不夠,下面是一些我認為比較好的文章:

開發團隊的隨感:http://www.aosabook.org/en/matplotlib.html

公眾號《王的機器》推文:https://mp.weixin.qq.com/s/vUaIfjM7R2Ac3ICPBh39UQ

以及最重要的API文檔:

http://www.matplotlib.org/

下面是本文的索引。

1.三種繪圖模式

在matplotlib的網上教程中,經常可以看到很多種作圖模式,繪製出一樣的圖。

有時候容易凌亂,因此做一個簡單的梳理。

根據繪圖理念的不同,分成了3種。

不同的繪圖模式,本質上是利用了Matplotlib的不同層提供的接口,在下一節會具體介紹。

本文的重點會放在面向對象上。

1.pylab

函數式作圖,最接近matlab,但是不推薦。

from pylab import *

2.pyplot交互式

(適合IPython這種交互式編輯器,本質上是利用pyplot腳本層對底層的封裝,使得繪圖非常簡單)

非常簡單的交互式作圖,直接根據命令作圖,但個性化能力有限。

import matplotlib.pyplot as plt
 import numpy as np
 x = np.arange(1,11)
 y = np.random.random(10)

 plt.plot(x,y)
 plt.title('pyplot')
 plt.show()

3.面向對象式

最接近底層的作圖模式,貫徹了萬物皆對象的理念,可以定製很多高難度的圖。

流程可以表述為:

FigureCanvas 實例實例化 Figure實例(添加到畫板上)

使用 figure 實例創建一個或多個 Axes 或 Subplot 實例(放置畫紙)

使用 Axes實例方法創建 具體構圖零件。(畫畫)

import numpy as np
from matplotlib.backends.backend_agg import 
FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure

fig = Figure()
canvas = FigureCanvas(fig)

x = np.random.randn(10000)
ax = fig.add_subplot(111)
ax.hist(x, 100)
fig.savefig('matplotlib_histogram.png')

但有時候,我們也會將交互式與面向對象式進行結合,比如:

import matplotlib.pyplot as plt
import numpy as np
x = np.arange(1,11)
y = np.random.random(10)

fig = plt.figure()

ax1 = fig.add_subplot(1,1,1)

plt.plot(x,y)

ax1.set_title('object oriented')

對於面向對象式+交互式結合的方法,一個基本的繪圖流程可以表述為:

創建一個 figure 實例;使用 figure 實例創建一個或多個 Axes 或 Subplot 實例;使用 Axes實例方法創建具體構圖零件。

2.面向對象繪圖基礎

參考資料:

http://www.aosabook.org/en/matplotlib.html

matplotlib有三層結構。

三層結構可以看作一個棧結構。上一層的layer懂得如何調用下一層layer,但下一層的layer無法調用上層的layer.

棧結構如圖:

自頂向下依次是scripting artist backend

2.1 matplotlib三層結構1.backend

參考資料:

https://matplotlib.org/3.1.0/api/backend_bases_api.html

後端層

後端層有三個內置的抽象接口類:
FigureCanvas(類似於畫板):即matplotlib.backend_bases.FigureCanvas,它定義並包含繪製圖形的區域。對於一些UI工具(例如:Qt),FigureCanvas內部有具體的實現,它知道如何把自己(畫板)插入到一個UI界面中,也知道如何調用Renderer繪製到Canvas上,同時,一些UI操作事件也可以被自動轉化為matplotlib Event。

Renderer(類似於畫筆):即matplotlib.backend_bases.Renderer,Renderer類的一個實例用於在圖形畫布上繪製。它是一個基於像素的核心渲染器,調用了C++的:Anti-Grain Geometry(Agg)。Agg是一個C ++高性能圖像模板庫,基於像素的核心渲染器。這是一個高性能庫,用於渲染消除鋸齒的2D圖形,從而生成有吸引力的圖像。matplotlib提供了將像素緩衝區插入到交互界面的支持,這些像素由agg後端渲染產生。因此可以跨UI和作業系統獲得像素精確的圖形。

Event(事件,由用戶定義):即matplotlib.backend_bases.Event,處理用戶輸入,如鍵盤敲擊和滑鼠點擊。Event框架把鍵盤/滑鼠事件映射到了2個類KeyEvent 和 MouseEvent上,用戶通過觸發事件,框架內部就會調用相關函數。

2.artist

artist層包含了一個最主要的對象Artist。Artist對象知道如何獲取Renderer實例,並使用它在Canvas實例上進行畫畫。
我們在Matplotlib圖上看到的所有內容都是Artist實例。
包括 title, line ,tick labels,images等等。

20191016214512.png

matplotlib.artist.Artist是所有Artist類的基類,它包含了所有Artist類共有的屬性:將artist對象的坐標系統轉化成canvas對象的坐標系統。

artist對象如何與backend發生耦合?

artist對象的類必須實現draw方法,該方法能夠從後端傳入render實例,由於render實例有一個指向想要繪製的canvas類型(可以是PDF,SVG等)的指針,因此,它會調用合適的方法在上面進行繪製。


class SomeArtist(Artist):
    'An example Artist that implements the draw method'

    def draw(self, renderer):
        """Call the appropriate renderer methods to paint self onto canvas"""
        if not self.get_visible():  return

        
        renderer.draw_path(graphics_context, path, transform)

Artist對象有兩種類型

第一種類型是原始類型(primitive type):例如Line2D, Rectangle, Circle, Text類 的實例。

第二種類型是複合類型(composite type),例如Figure,Axes,Tick,Axis類的實例。

幾個重要的點:

1.figure Artist是一個圖中所有元素的頂層對象,包含並管理這些元素。

2.composite type中最重要的對象是axes,因為它是matplotlib API幾乎所有方法發揮作用的地方,包括創建並操縱刻度線(ticks),軸線(axis lines),grid或background。

3.一個composite type可以包含其他的composite type以及primitive type。比如:一個figure(畫布)可以包含多個坐標軸(axes)以及text等元素,它的背景是Rectangle實例。




from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
fig = Figure()
canvas = FigureCanvas(fig)


import numpy as np
x = np.random.randn(10000)






ax = fig.add_subplot(111)




ax.hist(x, 100)


ax.set_title('Normal distribution with $\mu=0, \sigma=1$')
fig.savefig('matplotlib_histogram.png')

下圖模擬了人類繪畫與matplotlib繪畫的過程:

20191016214856.png
3.腳本層(script layer)

為非專業程式設計師的科學家開發,腳本層本質上是Matplotlib.pyplot接口,它將定義畫布(canvas)和定義figure artist實例的過程自動化,並連接它們,因此,腳本層本質上是前兩層的wrapper。

pyplot接口是圍繞核心Artist API的一個相當薄的包裝器,它試圖通過使用最少量樣板代碼暴露腳本接口中的API函數。

通過matplotlib提供的狀態腳本接口,可快速輕鬆以MATLAB繪圖風格繪製圖形。

來看一個通過腳本層繪圖的實例。(本質上是前面提到的交互式方式)




import matplotlib.pyplot as plt
import numpy as np

x = np.random.randn(10000)


plt.hist(x, 100)


plt.title(r'Normal distribution with $\mu=0, \sigma=1$')
plt.savefig('matplotlib_histogram.png')


plt.show()

而事實上,我們絕大多數用戶使用的都是腳本層的接口。僅僅使用一個plt函數(import matplotlib.pyplot as plt),就能夠完成絕大多數繪圖。

為什麼腳本層無需要指定fig就可以實現繪圖?

Pyplot 為底層繪圖庫對象提供了有限狀態機接口,從而引入了當前軸(current axes) 的概念。

state-machine 會自動和以用戶無感的方式創建 Figures(圖)對象 和 axes (軸域),以實現所需的繪圖操作。

具體一點: plt.plot() 的第一個調用將自動創建 Figure 和 Axes 對象,以實現所需的繪圖。對 plt.plot() 後續的調用會重複使用當前 Axes 對象,並每次添加一行。設置 title 標題、legend 圖例等,都會使用當前 Axes 對象,設置相應的 Artist。

利用一個簡版的例子來看一下腳本層是如何對artist和canvas進行包裝的。






@autogen_docstring(Axes.plot)
def plot(*args, **kwargs):
    ax = gca()

    ret = ax.plot(*args, **kwargs)
    draw_if_interactive()

    return ret

2.2 Artist:輔助顯示層

Canvas是位於最底層的系統層,在繪圖的過程中充當畫板的角色,即放置畫布的工具。

通常情況下,我們並不需要對Canvas特別的聲明,但是當我需要在其他模塊如PyQt中調用Matplotlib模塊繪圖時,就需要首先聲明Canvas,這就相當於我們在自家畫室畫畫不用強調要用畫板,出去寫生時要特意帶一塊畫板。

Figure是Canvas上方的第一層,也是需要用戶來操作的應用層的第一層,在繪圖的過程中充當畫布的角色。
當我們對Figure大小、背景色彩等進行設置的時候,就相當於是選擇畫布大小、材質的過程。因此,每當我們繪圖的時候,寫的第一行就是創建Figure的代碼。

Axes是應用層的第二層,在繪圖的過程中相當於畫布上的繪圖區的角色。 一個Figure對象可以包含多個Axes對象,每個Axes都是一個獨立的坐標系,繪圖過程中的所有圖像都是基於坐標系繪製的。

總結:對於普通用戶,只需要記住:Figure是畫布,axes是繪畫區,axes可以控制每一個繪圖區的屬性。

20191016215541.png
1.figure:畫布

本節會做一個基本介紹。

創建figure

創建一個畫布,可以指定很多參數

import matplotlib.pyplot as plt

fig = plt.figure(
num = None,               
figsize=None,             
dpi=None,                 
facecolor=None,           
edgecolor=None, frameon=True,    
FigureClass=<class 'matplotlib.figure.Figure'>,   
clear=False,                     

**kwargs)
e.g.
fig = plt.figure(num=1,figsize = [10,10],dpi=400,
                 facecolor = 'grey',
                edgecolor = 'blue')

這樣,我們創建出來的畫布就是灰色的了

創建多個畫布

當然,順著面向對象的概念,也可以創建多個畫布,即:創建多個畫布對象即可。

fig1 = plt.figure()
ax11 = fig1.add_subplot(1,1,1)
ax11.plot([1,2],[1,2])

fig2 = plt.figure()
ax21 = fig2.add_subplot(1,1,1)
ax21.plot([1,2],[1,2])

figure的屬性

參考

https://matplotlib.org/api/asgen/matplotlib.figure.Figure.html

figure來自matplotlib.figure.Figure類,Figure繼承了Artist類,是所有繪圖元素的頂層容器。

通過pyplot腳本層進行包裝,我們可以直接通過plt.figure()調用該類。

Figure的屬性包含了 Patch,在笛卡爾坐標中,patch 是 Rectangle,在極坐標中是 Circle。這個 patch 確定了繪圖區的 shape,background 和 border。

笛卡爾坐標系統的fig(默認)通過屬性Rectangle實例對其background patch進行填充,見下面的實現:

self.patch = Rectangle(
            xy=(0, 0), width=1, height=1,
            facecolor=facecolor, edgecolor=edgecolor, linewidth=linewidth,
            visible=frameon)

fig一些常見的屬性與方法
import matplotlib.pyplot as plt
fig = plt.figure()


print(fig)

fig.suptitle('this is a test')

獲取figure包含的對象

figure.patch


figure.axes

例子:
for ax in fig.axes:
    ax.axis('off')

for ax in fig.axes:
    ax.grid(True)

例子1:

20191016220004.png

例子2:


for ax in fig.axes:
    rect = ax.patch
    rect.set_facecolor('g')
    rect.set_alpha(0.1)

效果:

20191016220040.png

下表是 figure 包含的一些Artist

1571234511(1).png
figure的getter/setter

僅僅舉幾個例子,後面會經常看到

setter:
fig.set_edgecolor()
fig.set_facecolor()


getter:
##返回一個axes列表,可以對坐標軸進行控制
fig.get_axes()

2.axes:坐標系繪圖區介紹

matplotlib.axes.Axes 是 matplotlib 的核心。它包含了 figure 中使用的 大部分Artist ,而且包含了許多創建和添加 Artist 的方法。

當然這些函數也可以獲取和自定義 Artists。
axes擁有很多屬性。

這些屬性本質上是一個對象,都屬於artist基類。

關係如下:

20191016220451.png

一個簡單的例子:

20191016220508.png

•    spines: 指的是axes邊框部分,分為上下左右。

•    patch:指的是spin圍成的2D區域

•    line:設置線條(顏色、線型、寬度等)和標記

•    ticks:指的是刻度線

axes與subplot的區別

我們常常在一些教程中看到一幅圖內嵌套了多個圖,或者一個圖內分成了好多子圖。

一幅圖 (Figure) 中可以有多個坐標系 繪圖區(Axes),
一幅圖中可以有多幅子圖繪圖區 (Subplot),
那麼坐標系和子圖是不是同樣的概念?

在絕大多數情況下是的,兩者有一點細微差別:

坐標系在母圖中的網格結構可以是不規則的,子圖subplot是坐標系axes的一個特例,子圖在母圖中的網格結構必須是規則的,而坐標系在母圖中的網格結構可以是不規則的。由此可見,子圖是坐標系的一個特例。

(subplot就是自動整齊的排列好子圖了,axes就是自己手動排,就更靈活和麻煩。)

創建axes

關於axes 子圖的排版,詳細的參考:

https://matplotlib.org/tutorials/intermediate/gridspec.html#sphx-glr-tutorials-intermediate-gridspec-py

axes的創建方式
坐標系繪圖法比子圖更通用,更靈活,當然也更難。
常見的有3種生成方式
•    用 gridspec 包加上 subplot()

•    fig.add_axes()

•    用 plt.axes()

plt.axes([l,b,w,h])

其中 [l, b, w, h] 可以定義坐標系:

l 代表坐標系左邊到 Figure 左邊的水平距離

b 代表坐標系底邊到 Figure 底邊的垂直距離

w 代表坐標系的寬度

h 代表坐標系的高度

1.用 gridspec 包加上 subplot()

import matplotlib
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

fig2 = plt.figure(constrained_layout=True)
spec2 = gridspec.GridSpec(ncols=2, nrows=2, figure=fig2)
f2_ax1 = fig2.add_subplot(spec2[0, 0])
f2_ax2 = fig2.add_subplot(spec2[0, 1])
f2_ax3 = fig2.add_subplot(spec2[1, 0])
f2_ax4 = fig2.add_subplot(spec2[1, 1])

利用切片形式進行更加個性化的定製:
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

fig3 = plt.figure(constrained_layout=True)
G = gridspec.GridSpec(ncols=3, nrows=2, figure=fig3)
ax1 = fig3.add_subplot(G[0,:])
ax2 = fig3.add_subplot(G[1,:2])
ax3 = fig3.add_subplot(G[1,2])


ax1.set_xticklabels('')

for i in ax1.xaxis.get_ticklines():
    i.set_markersize(0)
    i.set_markeredgewidth(0)

ax1.set_yticklabels('')
for i in ax1.yaxis.get_ticklines():
    i.set_markersize(0)
    i.set_markeredgewidth(0)

20191016220735.png

繪製一個重疊圖:


plt.axes([0,0,1,1],facecolor = 'g')
plt.xticks([])
plt.yticks([])


plt.axes([0.2,0.2,1,1],facecolor = 'r')
plt.xticks([])
plt.yticks([])

plt.axes([0.4,0.4,1,1],facecolor = 'b')
plt.xticks([])
plt.yticks([])

20191016220803.png

2.fig.add_axes()

fig = plt.figure()
ax1 = fig. add_axes()
ax1.plot([1,2,3],[1,2,3])

ax2 = fig.add_axes([0.7,0.1,0.3,0.3])
ax2.plot([1,2,3],[1,2,3])

3.plt.axes() ##腳本層的封裝

###坐標系1
plt.axes([0.1,0.1,1,1])
plt.plot([1,2,3],[1,2,3])
###坐標系2
plt.axes([[0.7,0.1,0.3,0.3])
plt.plot([1,2,3],[1,2,3])
兩者效果是一樣的:

20191016220900.png

axes能不能做到和subplot效果相似?可以
只需要按照對應位置調整好坐標即可

###坐標系1
plt.axes([0.1,0.1,1,1])
plt.plot([1,2,3],[1,2,3])
###坐標系2
plt.axes([0.1,1.2,1,1])
plt.plot([1,2,3],[1,2,3])

axes的getter與setter

setter與getter是設計邏輯,幾乎所有的類對象都有setter與getter方法。通過getter與setter,能夠獲取/改變該實例的屬性。

通過setter getter可以獲取很多artist子類的屬性。

matplotlib文檔:https://matplotlib.org/api/axes_api.html#the-axes-class
有非常詳細的介紹。
一些常見的屬性如下:

ax.set_*
ax.get_*

*包括:
alpha
title
tick
xticks
yticks
label
xlabel
ylabel
xlim
ylim

#
ax.get_xaxis()
ax.get_yaxis()

#標籤+刻度構成了axis
#
ylabel
xlabel

#
xticklabels
yticklabels
get_legend_handles_label

...

也可以通過:
fig.axes[0].title()找到這些對象

#
ax.get_ylim()
ax1.set_ylim(0,5)

#
ax.set_ylabel('y_label',rotation =45)  ##旋轉45度

#一個batch setter
axes.set()

#e.g
ax2.set(xlim=[0,2], zorder=2)

獲取axes包含的對象

謹記:獲取對象的目的是為了調用屬於對象實例的方法。

比如:
通過ax.patch獲取了ax的patch,接下來通過調用patch的set_color函數進行設定顏色。

ax1.patch.set_color('g')
ax1.patch.set_alpha(0.1)

20191016221218.png
常見應用

ax.plot():折線圖

##當調用 ax.plot 時,會創建 Line2D 實例,並將實例添加到 Axes.lines 列表。
ax.plot([1,100],[1,100])
ax.plot([3,2],[3,2])
ax.lines

##lines列表記錄了plot生產的Line2D對象
[<matplotlib.lines.Line2D at 0x13a3d2f4f60>,
 <matplotlib.lines.Line2D at 0x13a3b01c198>]

ax.hist():頻率分布圖

ax.hist()會返回3個對象:
#n:頻率
#bins:箱子的橫坐標
#patches:每一個箱子patch構成的列表,可以通過patches的索引追蹤到每一個patch,並進行人為操作
n, bins, patches = ax.hist(np.random.randn(1000), 50,
    facecolor='yellow', edgecolor='yellow')

要注意,對patch進行操作也有一系列setter和getter,參考patch一節。

3.subplot:子圖繪圖區

子圖subplot是坐標系axes的一個子類,即:一個特例。
子圖在母圖中的網格結構必須是規則的,而坐標系在母圖中的網格結構可以是不規則的。

創建subplot有2種方式(仍舊是第一節提到的三種作圖模式種的後兩種):交互式和面向對象式。
其中交互式和面向對象式又分別有兩種語法。

1.交互式(可以感覺到在繪製複雜圖形時,控制能力有限)

import matplotlib.pyplot as plt
import numpy as np
x = np.arange(1,11)
y = np.random.random(10)

plt.subplot(121)
plt.plot(x,y)

plt.subplot(122)
plt.plot(x,y)

plt.show()


import matplotlib.pyplot as plt
import numpy as np

x = np.arange(1,11)
y = np.random.random(10)

ax1 = plt.subplot(1,2,1)
ax2 = plt.subplot(1,2,2)

ax1.plot(x,y)
ax2.plot(x,y)

2.面向對象式(1):

利用add_subplot
x = np.arange(1,11)
y = np.random.random(10)

fig = plt.figure() 
ax1 = fig.add_subplot(1,2,1)  
ax2 = fig.add_subplot(1,2,2)  

ax1.plot(x,y)
ax2.plot(x,y)
上面語句的等價於:
x = np.arange(1,11)
y = np.random.random(10)

fig, axes = plt.subplots(1,2) 

axes[0].plot(x,y)

axes[1].plot(x,y)

•    創建子圖的形式總結:

1.(不推薦)交互式:直接用plt.subplot按順序操縱

2.面向對象:
ax1 = fig.add_subplot() ##最容易理解
plt.subplots() axes[0],axes[1] ##也不錯

4.primitive typeLine2D

https://matplotlib.org/api/_as_gen/matplotlib.lines.Line2D.html

Patch:形狀

參考:

https://matplotlib.org/api/_as_gen/matplotlib.patches.Patch.html#matplotlib.patches.Patch

patch類繼承了artist,一個patch是一個2d的artist實例,包含了填充顏色+邊框顏色。如果沒有對其進行設置,會根據rc params的默認參數進行設置。

這點可以從Patch類的實現中看出:

def __init__(self,
                 edgecolor=None,
                 facecolor=None,
                 color=None,
                 linewidth=None,
                 linestyle=None,
                 antialiased=None,
                 hatch=None,
                 fill=True,
                 capstyle=None,
                 joinstyle=None,
                 **kwargs):
        """
        The following kwarg properties are supported

        %(Patch)s
        """
        artist.Artist.__init__(self)

        if linewidth is None:
            linewidth = mpl.rcParams['patch.linewidth']
        if linestyle is None:
            linestyle = "solid"
         ...

patch對象由matplotlib.patches.Patch生成。
使用時,我們可以通過如下代碼進行調用:

import matplotlib.patches as mpatches
import matplotlib.pyplot as plt

red_patch = mpatches.Patch(color='red', label='The red data')
plt.legend(handles=[red_patch])

plt.show()

•    創建常見的patch子類

很多常見的形狀繼承了patch類,包括:Rectangle、Circle、Polygon等,(matplotlib.patches.Rectangle類等)
創建一個具體的形狀本質上是在調用它的構造函數,構造函數有許多的參數可選,需要查閱具體文檔。
使用時,我們可以通過如下代碼進行調用:

import matplotlib.patches as mpatches


grid = np.mgrid[0.2:0.8:3j, 0.2:0.8:3j].reshape(2, -1).T


rect = mpatches.Rectangle(grid[1] - [0.025, 0.05], 0.05, 0.1, ec="none")


polygon = mpatches.RegularPolygon(grid[3], 5, 0.1)


arrow = mpatches.Arrow(grid[5, 0] - 0.05, grid[5, 1] - 0.05, 0.1, 0.1,
                       width=0.1)


import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)

rect = plt.Rectangle([0.1,0.1],0.5,0.3,facecolor= 'g')
cir = plt.Circle([0.5,0.5],0.1)
ax.add_patch(rect)
ax.add_patch(cir)
plt.show()

效果:

20191016222255.png

•    將Patch添加到axes中


ax.add_patch()



patches=[]      
patches.append(e1)   
patches.append(e2)
collection=PatchCollection(patches)  
ax.add_collection(collection)    

•    通過setter/getter更改/查詢patch的屬性。
rectangle、circle等patch子類中內置了大量getter/setter,可以方便獲取/改變對應屬性。看一個例子:

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)

rect = plt.Rectangle([0.1,0.1],0.5,0.3,facecolor= 'g')
cir = plt.Circle([0.5,0.5],0.1)
ax.add_patch(rect)
ax.add_patch(cir)
plt.axis('off')
plt.show()



rect.get_fill()
rect.get_path()

rect.set_x(0.5)
rect.set_y(0.5)

圖像中的矩形發生了位移:

20191016222351.png

最後,要強調一點,所有封裝好的形狀本質上都是通過Path來進行實現的,換句話說,通過path類,我們能夠創建一些更複雜的自定義形狀。

Path:自定義形狀

參考:
https://matplotlib.org/api/path_api.html

所有封裝好的形狀本質上都是通過Path來進行實現的,換句話說,通過path類,我們能夠創建一些更複雜的自定義形狀。
要想通過path類繪製patch,
首先,需要定義好頂點(vertice)的位置以及對應的code(表明vertex的類)。
code類型包括:

1.STOP

2.MOVETO:移動到當前頂點

3.LINETO:畫一條線到當前頂點

4.CURVE3:繪製2次貝塞爾曲線到當前頂點

5.CURVE4:繪製3次貝塞爾曲線到當前頂點

6.CLOSEPOLY:Draw a line segment to the start point of the current polyline.(封閉點)

通過一個例子來看看path類如何產生變量:

import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches


verts = [
    (0., 0.), 
    (0., 1.), 
    (1., 1.), 
    (1., 0.), 
    (0., 0.)
]

codes = [Path.MOVETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.CLOSEPOLY]

path = Path(verts,codes) 



fig = plt.figure()
ax = fig.add_subplot(111)


patch = patches.PathPatch(path, facecolor='orange', lw=2)


ax.add_patch(patch)



ax.set_xlim(-2,2)
ax.set_ylim(-2,2)
plt.show()

事實上,python中的histogram barplot等基礎的圖像也是通過path實現的,比如一個例子:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.path as path

fig = plt.figure()
ax = fig.add_subplot(111)


np.random.seed(19680801)


data = np.random.randn(1000)

n, bins = np.histogram(data, 100)
print(data.shape,n.shape,bins.shape,sep='   ')


left = np.array(bins[:-1])
right = np.array(bins[1:])
bottom = np.zeros(len(left))
top = bottom + n
nrects = len(left)

nverts = nrects*(1+3+1)
verts = np.zeros((nverts, 2))
codes = np.ones(nverts, int) * path.Path.LINETO
codes[0::5] = path.Path.MOVETO
codes[4::5] = path.Path.CLOSEPOLY
verts[0::5,0] = left
verts[0::5,1] = bottom
verts[1::5,0] = left
verts[1::5,1] = top
verts[2::5,0] = right
verts[2::5,1] = top
verts[3::5,0] = right
verts[3::5,1] = bottom



barpath = path.Path(verts, codes)
patch = patches.PathPatch(barpath, facecolor='green', edgecolor='yellow', alpha=0.5)


ax.add_patch(patch)

ax.set_xlim(left[0], right[-1])
ax.set_ylim(bottom.min(), top.max())

plt.show()

可以得到:

20191016222542.png
5.練習:通過path定義一個fastqc背景圖

import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches

class QualityBoxplot(object):
    def __init__(self,seq_len = 200):



        
        self.__seq_len = seq_len
        self.__fig = plt.figure()
        self.__ax = self.__fig.add_subplot(111)
        self.__ax.set_ylim(0,40)
        self.__ax.set_xlim(0,self.__seq_len)
        
        self.__fig.set_size_inches([15,12])
        
        self.__low_quality_path()
        self.__mid_quality_path()
        self.__high_quality_path()



    def __low_quality_path(self):
        for i in range(self.__seq_len):
            verts = [
                (i, 0), 
                (i, 20), 
                (i+1, 20), 
                (i+1, 0.), 
                (i, 0.)
            ]
            codes = [Path.MOVETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.CLOSEPOLY]
            path = Path(verts,codes) 
            
            if (i % 2) == 0:
                patch = patches.PathPatch(path, facecolor='r', lw=0.1,alpha = 0.1)
            else:
                patch = patches.PathPatch(path, facecolor='r', lw=0.1,alpha = 0.3)

            
            self.__ax.add_patch(patch)

    def __mid_quality_path(self):
        for i in range(self.__seq_len):
            verts = [
                (i, 20),
                (i, 30),
                (i+1, 30), 
                (i+1, 20.), 
                (i, 20)   
            ]
            codes = [Path.MOVETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.CLOSEPOLY]
            path = Path(verts,codes) 

            if (i % 2) == 0:
                patch = patches.PathPatch(path, facecolor='y', lw=0.1,alpha = 0.1)
            else:
                patch = patches.PathPatch(path, facecolor='y', lw=0.1,alpha = 0.3)

            self.__ax.add_patch(patch)

    def __high_quality_path(self):
        for i in range(self.__seq_len):
            verts = [
                (i, 30),
                (i, 40),
                (i+1, 40), 
                (i+1, 30.), 
                (i, 30)   
            ]
            codes = [Path.MOVETO,Path.LINETO,Path.LINETO,Path.LINETO,Path.CLOSEPOLY]
            path = Path(verts,codes) 

            if (i % 2) == 0:
                patch = patches.PathPatch(path, facecolor='g', lw=0.1,alpha = 0.1)
            else:
                patch = patches.PathPatch(path, facecolor='g', lw=0.1,alpha = 0.3)

            self.__ax.add_patch(patch)

if __name__ == '__main__':
    qc =  QualityBoxplot()    

效果:

20191016222718.png
6.composite type

figure
已在前面有了介紹。

axes
已在前面有了介紹。

axis

下圖中可以看到Axis(軸)由標籤(label)+刻度tick構成。

20191016223232.png

舉個例子

20191016223257.png


ax.get_xticks()

array([-4., -3., -2., -1.,  0.,  1.,  2.,  3.,  4.,  5.])


axis = ax.xaxis
axis.get_ticklocs()

array([-4., -3., -2., -1.,  0.,  1.,  2.,  3.,  4.,  5.])

ax.get_xlabel()

'time (s)'


ax.get_xticklabels()

for i in ax1.get_xticklabels():
    print(i)

ax.set_xticks([0,1,2,3,5,6])
ax.set_xlabel('This is a x label')

效果:

20191016223336.png

以上講的幾乎都是ax的方法,下面看一些屬於axis的方法和屬性

axis = ax.xaxis

xis.get_ticklocs()
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])

axis.get_ticklabels()
<a list of 10 Text major ticklabel objects>




axis.get_ticklines()
<a list of 20 Line2D ticklines objects>


axis.get_ticklines()
<a list of 20 Line2D ticklines objects>


axis.get_ticklines(minor=True)
<a list of 0 Line2D ticklines objects>

下面是 axis 的一些非常有用的獲取方法,都由相對應的設置方法:

1571236522.png

一些例子




for i in ax1.xaxis.get_ticklabels():
    print(i)
    i.set_rotation(45)

20191016223803.png



for i in ax1.xaxis.get_ticklines():
    print(i)
    i.set_markersize(10)
    i.set_markeredgewidth(3)

20191016223821.png





j = 0
for i in ax1.xaxis.get_ticklines():
    j+=1
    if (j % 3) ==0:
        print(i)
        i.set_markersize(0)
        i.set_markeredgewidth(0)

20191016223840.png

如果想要針對性的刪除某幾個刻度,可以直接根據索引取到相應的位置,把寬度和長度設為0即可。

##刪除第3個刻度
ax1.xaxis.get_ticklines()[6].set_markersize(0)
ax1.xaxis.get_ticklines()[6].set_markeredgewidth(0)

tick

tick也是一個組成類型,它由具體的tick label與grid line構成,這些都可以直接作為 Tick 的屬性而被獲取。還有一些布爾值變量用來控制是否設置 x 軸上方 ticks 和 labels,y 軸右側 ticks 和 labels。

通過一副圖來看一下什麼是tick label,什麼是grid line

20191016223621.png

1571236593(1).png

在前面axis一節,我們會發現ticklabel的對象個數是顯示出來個數的2倍,另一半被隱藏起來了,這一節我們試圖顯示另一半。

for i in ax1.xaxis.get_major_ticks():
    i.label1On = True
    i.label2On = True

20191016223723.png
locator:決定tick location

class matplotlib.ticker.Locator是一個單獨的類,用於決定tick的在spine上的排布特點。
在實際使用的時候,並不需要過多關注locator這個類的具體內容,只需要清楚它可以作為ax.xaxis.set_major_locator()的一個參數傳遞即可。
有很多種locator類型,不同的 locator() 可以生成不同的刻度對象,我們來研究以下 8 種:

NullLocator(): 空刻度

MultipleLocator(a): 刻度間隔 = 標量 a

FixedLocator(a): 刻度位置由數組 a 決定

LinearLocator(a): 刻度數目 = a, a 是標量

IndexLocator(b, o): 刻度間隔 = 標量 b,偏移量 = 標量 o

AutoLocator(): 根據默認設置決定

MaxNLocator(a): 最大刻度數目 = 標量 a

LogLocator(b, n): 基數 = 標量 b,刻度數目 = 標量 n

下面是一些例子

import numpy as np
import matplotlib.pyplot as plt


fig = plt.figure(figsize = (10,24))
fig.tight_layout()
def init(ax):
    ax.spines['top'].set_color(None)
    ax.spines['right'].set_color(None)
    ax.spines['left'].set_color(None)
    for i in ax.yaxis.get_ticklabels():
        i.set_fontsize(0)
    for i in ax.yaxis.get_ticklines():
        i.set_markersize(0)
        i.set_markeredgewidth(0)        

    
    for i in ax.xaxis.get_ticklines():
        
        i.set_markersize(8)
        i.set_markeredgewidth(2)
        

    
    for i in ax.xaxis.get_ticklabels():
        i.set_fontsize(20)
        i.set_fontfamily('serif')



ax1 = fig.add_subplot(611)
init(ax1)
ax1.xaxis.set_major_locator(ticker.NullLocator())
ax1.text(0,0.1,'ax1 Nulllocator',fontsize = 20)




ax2 = fig.add_subplot(612)
init(ax2)

ax2.xaxis.set_major_locator(ticker.MultipleLocator(0.5))

ax2.xaxis.set_minor_locator(ticker.MultipleLocator(0.1))

for i in ax2.xaxis.get_minorticklines():
    i.set_markersize(5)
    i.set_markeredgewidth(2)
ax2.text(0,0.1,'ax2  Multiplelocator',fontsize = 20)


ax3 = fig.add_subplot(613)
init(ax3)
ax3.xaxis.set_major_locator(ticker.FixedLocator([0,0.1,0.5,1]))
ax3.xaxis.set_minor_locator(ticker.FixedLocator([0.02,0.04,0.06,0.08]))

for i in ax3.xaxis.get_minorticklines():
    i.set_markersize(5)
    i.set_markeredgewidth(2)
ax3.text(0,0.1,'ax3  Fixedlocator',fontsize = 20)







ax4 = fig.add_subplot(614)
init(ax4)

ax4.xaxis.set_major_locator(ticker.LinearLocator(3))

ax4.xaxis.set_minor_locator(ticker.LinearLocator(10))

for i in ax4.xaxis.get_minorticklines():
    i.set_markersize(5)
    i.set_markeredgewidth(2)
ax4.text(0,0.1,'ax4  Linear locator',fontsize = 20)



plt.subplots_adjust(hspace =0.2)

20191016224016.png
Fommator:設定坐標格式

def format_func(value, tick_number):
    
    N = int(np.round(2 * value / np.pi))
    if N == 0:
        return "0"
    elif N == 1:
        return r"$\pi/2$"
    elif N == 2:
        return r"$\pi$"
    elif N % 2 > 0:
        return r"${0}\pi/2$".format(N)
    else:
        return r"${0}\pi$".format(N // 2)

ax.xaxis.set_major_formatter(plt.FuncFormatter(format_func))
fig

20191016224045.png

也可以通過set_yticklabels()函數來自定義tick label內容。

ax1.set_yticklabels(['a','b','c','d'])

20191016224102.png
7.坐標軸練習實例

通過幾個實例,來全面鞏固一下坐標軸的DIY畫法


    for spine in ["left", "top", "right"]:
        ax.spines[spine].set_visible(False)

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

fig = plt.figure(figsize = (10,24))
fig.tight_layout()
def init(ax):
    for spine in [ "top", "right"]:
        ax.spines[spine].set_visible(False)

ax1 = fig.add_subplot(611)
init(ax1)


ax1.patch.set_color('orange')
ax1.patch.set_alpha(0.5)




for i in ax1.yaxis.get_ticklabels():
    i.set_fontsize(0)



for i in ax1.yaxis.get_ticklines():
    i.set_markersize(0)
    i.set_markeredgewidth(0)



for i in ax1.xaxis.get_ticklabels():
    i.set_fontsize(20)
    i.set_fontfamily('serif')
    i.set_color('orange')
    i.set_rotation(45)


for i in ax1.xaxis.get_ticklines():
    
    i.set_markersize(8)
    i.set_markeredgewidth(2)
    i.set_color('orange')



ax1.spines['left'].set_linewidth(2)
ax1.spines['left'].set_color('orange')


ax1.set_ylabel('ax1 ylabel',fontsize = 20,color = 'orange')
ax1.set_xlabel('ax1 xlabel',fontsize = 20,color = 'orange')



ax1.spines['bottom'].set_linewidth(2)
ax1.spines['bottom'].set_color('orange')



ax1.set_title('ax1 title',fontsize = 20,color = 'orange')






ax2 = fig.add_subplot(612)
init(ax2)


cur_labels = [item.get_text() for item in ax2.get_xticklabels()]
new_labels = ['tick1','tick2','','','tick5']
ax2.set_xticklabels(new_labels)










ax2.tick_params('x',direction = 'in')
for i in ax2.xaxis.get_ticklines():
    
    i.set_markersize(8)
    i.set_markeredgewidth(2)





ax3 = fig.add_subplot(613)
init(ax3)


ax3.spines['top'].set_visible(True)
ax3.twiny()



plt.subplots_adjust(hspace =2)

20191016224208.png
8.Legend:圖例Legend介紹

在matplotlib中,Legend本質是一個composite type,也叫一個容器類,由handle和text對象組成。

通常不需要用戶顯示的創建一個Legend實例,而是直接通過調用ax.legend()函數返回一個legend對象,從而創建圖例。

一個legend由一個或多個entry組成。

Legend = entry1+(entry2)+…

entry=key+label

key:圖標

label:text描述

handle(句柄):用於產生entry的原始對象。(比如散點,曲線等;)

.legend()

Ax 或figure調用legend()函數會返回一個legend對象。

例子1:自動添加legend

一個簡單的例子來說明什麼是handle,什麼是label:

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
fig.subplots_adjust(top=0.8)
ax1 = fig.add_subplot(211)
ax1.set_ylabel('volts')
ax1.set_title('a sine wave')

t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
line, = ax1.plot(t, s, color='blue',label='sin plot', lw=2)
ax1.legend()

handles, labels = ax1.get_legend_handles_labels()

通過axes.get_legend_handles_labels()可以獲取到handles對象以及labels,不難發現,在本例,handles是一個Line2D對象,labels是一個Text文本列表

20191016224448.png

20191016224454.png

axes.get_legend_handles_labels()
該函數會返回一個handles(或者說能夠轉化成handles的artist對象)列表。

例子2:手動添加legend

import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(211)
scatters= ax1.scatter([1,3,4],[2,3,5])


ax1.legend()

20191016224531.png

例子2可以看出,如果在創建一個散點對象(handle)時,沒有指定label,那麼即使調用了legend()函數,也不會把handle和label放進legend對象中。
解決方案:

要麼在創建散點時,指定Label:
scatters= ax1.scatter([1,3,4],[2,3,5],label='scatter')

要麼手動添加handles 與對應的labels

20191016224554.png

一些常見的用法

##由於已經有了label,因此調用legend不需要再指定label
line_up, = plt.plot([1,2,3], label='Line 2')
line_down, = plt.plot([3,2,1], label='Line 1')
plt.legend(handles=[line_up, line_down])

##該圖顯示的label是'Line Up', 'Line Down'
line_up, = plt.plot([1,2,3], label='Line 2')
line_down, = plt.plot([3,2,1], label='Line 1')
plt.legend([line_up, line_down], ['Line Up', 'Line Down'])

例子3:自定義legend
要注意,並不是所有artist對象都能添加到legend。
也並不是handles必須存在於axes中才能添加到legend上,可以人為添加。

import matplotlib.patches as mpatches
import matplotlib.pyplot as plt

red_patch = mpatches.Patch(color='red', label='The red data')
plt.legend(handles=[red_patch])

plt.show()

20191016224715.png
legend其他應用

Legend位置設置

位置設置有3種方法:

1.調用legend()函數的loc參數
Axes.legend()中的參數loc可以指定位置。

20191016224827.png

e.g
ax1.legend(handles=[scatters],labels=['add a scatter'],loc=1)

2.調用legend()函數的bbox_to_anchor參數。(2個或4個浮點構成的tuple)

4元組:(x, y, width, height)

2元組:(x, y)

3.loc參數與bbox_to_anchor參數相結合。


ax1.legend(loc='lower left',bbox_to_anchor=(0.5, 0.5)


ax1.legend(loc='upper left',bbox_to_anchor=(0.5, 0.5)

20191017092522.png

設置多個legend

如果多次調用ax.legend(),只能不斷地更新,並只顯示1個legend.

如果想要添加多個legend,可以參考下面的例子:

20191017092445.png

交換legend順序

import numpy as np
import matplotlib.pyplot as plt

generate random data for plotting
x = np.linspace(0.0,100,50)

y2 = x*2
y3 = x*3
y4 = x*4
y5 = x*5
y6 = x*6
y7 = x*7

plot multiple lines
plt.plot(x,y2,label='y=2x')
plt.plot(x,y3,label='y=3x')
plt.plot(x,y4,label='y=4x')
plt.plot(x,y5,label='y=5x')
plt.plot(x,y6,label='y=6x')
plt.plot(x,y7,label='y=7x')

get current handles and labels
this must be done AFTER plotting
current_handles, current_labels = plt.gca().get_legend_handles_labels()

sort or reorder the labels and handles
reversed_handles = list(reversed(current_handles))
reversed_labels = list(reversed(current_labels))
call plt.legend() with the new values
plt.legend(reversed_handles,reversed_labels)
plt.show()

2.3 script層常用的函數

本質上,我們看到的plt.*()的形式,都是腳本層進行封裝後的函數。

plt.axis('equal')

plt.axis('off')

plt.xlabel('test')
plt.ylabel('')

腳本層提供了類似於MATLAB的編程語法,可以很輕鬆地畫出想要的圖形。由於實在太過簡單,這裡不詳細介紹。

補充:jupyter的魔法函數

利用jupyter notebook非常方便,下面是一些常用的魔法函數。

%matplotlib inline

優點:將inline作為後端傳遞,可強制在瀏覽器中呈現圖形。
局限:是無法在render後修改圖形。(換句話說,一旦圖片繪製完畢,無法進一步添加標題等零件。)

%matplotlib notebook

notebook後端能夠克服創建圖片後無法修改的問題。在notebook後端到位的情況下,如果調用了plt函數,它會檢查是否存在激活的figure對象,如果有,調用的任何函數都將作用於該figure對象。
如果激活的figure對象不存在,它會創建一個新figure對象。

例子:

20191017102028.png


相關焦點

  • 如何用matplotlib繪圖呢?
    什麼是matplotlib?使用過python做數據分析的小夥伴都知道,matplotlib是一款命令式、較底層、可定製性強、圖表資源豐富、簡單易用、出版質量級別的python 2D繪圖庫。matplotlib算是python繪圖的元老級庫,類似程式語言裡的C語言。很多其它的python繪圖庫是基於matplotlib開發的,比如seaborn、ggplot、plotnine、holoviews、basemap等。matplotlib可用於python腳本、python shell、jupyter notebook、web等。
  • matplotlib繪圖的核心原理講解
    作者:朱小五來自:凹凸數據(ID:alltodata)matplotlib是基於Python語言的開源項目,旨在為Python提供一個數據繪圖包。相信大家都用過它來數據可視化,之前我還分享過25個常用Matplotlib圖的Python代碼。
  • 專題第19篇:Python繪圖神器之matplotlib
    我的施工之路今天,繼續施工專題第19篇:Python繪圖神器:matplotlib(上)使用版本本文使用的 matplotlib 版本: 3.1.3使用的 NumPy版本: 1.18.1順便說一句,matplotlib 的近親是 NumPy,對其的親緣性最好,無縫支持。
  • 機器學習繪圖神器Matplotlib首秀!
    公眾號:尤而小屋作者:Peter編輯:Peter大家好,我是Peter~Matplotlib是一個非常經典的繪圖庫,甚至有人將numpy+pandas+matplotlib稱之為數據分析三劍客,足以說明這個庫的重要性。
  • Python 繪圖,我只用 Matplotlib(二)
    而且我們也可以方便地將它作為繪圖控制項,嵌入GUI應用程式中。本文主要走進 Matplotlib 的世界,初步學會繪製圖形。在學習繪製之前,先來了解下 Matplotlib 基礎概念。用於數學運算的庫,它是在安裝 matplotlib 時候順帶安裝的。
  • Python數據分析之matplotlib繪圖基礎
    marker:〜matplotlib.markers.MarkerStyle,可選,默認值:'o'cmap:〜matplotlib.colors.Colormap,可選,默認:無 一個〜matplotlib.colors.Colormap實例或註冊名稱, cmap僅在c是浮點數組時使用。如果沒有, 默認為rcimage.cmap。
  • Python 數據分析:Matplotlib 繪圖
    簡介Matplotlib 是 Python 提供的一個繪圖庫,通過該庫我們可以很容易的繪製出折線圖、直方圖、散點圖、餅圖等豐富的統計圖,安裝使用 pip install matplotlib 命令即可,Matplotlib 經常會與 NumPy 一起使用。
  • Python之matplotlib繪圖示例
    在使用matplotlib模塊時畫坐標圖時,往往需要對坐標軸設置很多參數,這些參數包括橫縱坐標軸範圍、坐標軸刻度大小、坐標軸名稱等。
  • 【Python】機器學習繪圖神器Matplotlib首秀!
    公眾號:尤而小屋作者:Peter編輯:PeterMatplotlib是一個非常經典的繪圖庫,甚至有人將numpy+pandas+matplotlib稱之為數據分析三劍客,足以說明這個庫的重要性。雖然Peter鍾情於Plotly,但掌握Matplotlib繪製技巧也非常重要。
  • matplotlib繪圖的完善及美化
    matplotlib繪圖的完善及美化
  • Python 繪圖庫 Matplotlib 入門教程
    /Matplotlib是一個Python語言的2D繪圖庫,它支持各種平臺,並且功能強大,能夠輕易繪製出各種專業的圖像。運行環境由於這是一個Python語言的軟體包,因此需要你的機器上首先安裝好Python語言的環境。關於這一點,請自行在網絡上搜索獲取方法。關於如何安裝Matplotlib請參見這裡:Matplotlib Installing。
  • 見識matplotlib:不常見的一面,折線圖!
    眾所周知,matplotlib是python繪圖的基礎包,能夠生成各種各樣2D或者3D的圖形,用法算是多而全的那種,下邊是matplotlib官網首頁作為例子的幾張圖,大家感受一下:什麼?醜拒?不不不,別激動!其實matplotlib一直是一個低調奢華有內涵的包,需要我們透過它樸實無華的外表認清它豐富多彩的內在,來康康這條妖嬈的曲線,有沒有感受到它的召喚?
  • 16 個實用的 Matplotlib 繪圖小技巧
    今天給大家介紹16個Matplotlib繪圖實用的小技巧:matplotlib.pyplot 對象中有個 title() 可以設置表格的標題。添加文字-text設置坐標和文字,可以使用 matplotlib.pyplot 對象中 text() 接口。其中 第一、二個參數來設置坐標,第三個參數是設置顯示文本內容。
  • Python matplotlib繪圖示例 - 繪製三維圖形
    Python matplotlib模塊是擴展的MATLAB的一個繪圖工具庫。
  • python - matplotlib繪圖
    一、繪圖基礎import matplotlib.pyplot as pltimport numpy as npimport tensorflow as tfimport pandas as pd>'''Matplotlib中的pyplot子庫可用來快速繪製二維圖表figure 創建畫布plot 繪製圖形show 顯示繪圖figure(num,figsize,dpi,facecolor
  • 「繪圖,讓科學生動起來」:Python-matplotlib繪圖(專題一)python環境搭建篇
    專題一:做個行動派,安裝python及相關軟體——搭建python-matplotlib繪圖環境
  • Matplotlib入門詳細教程
    那既然pyplot是核心繪圖模塊,為什麼不把其接口引入到頂層呢?那樣直接import matplotlib就行,而無需每次都import matplotlib.pyplot as plt了雖然pyplot是matplotlib下的子模塊,但二者的調用關係卻不是matplotlib調用pyplot,而是在pyplot中調用matplotlib,略顯本末倒置?
  • Matplotlib數據可視化!
    二、 Matplotlib 初識1. 例子Matplotlib的圖像是畫在figure(如windows,jupyter窗體)上的,每一個figure又包含了一個或多個axes(一個可以指定坐標系的子區域)。
  • ​分享16個Matplotlib 繪圖實用小技巧!
    來源丨網絡今天給大家介紹16個Matplotlib繪圖實用的小技巧,Matplotlib在Python數據分析裡有著非常廣泛的使用,而且很多做科研學術的同學都是用這個庫。下面整理了一些非常不錯的小技巧,建議大家收藏哦!
  • python:matplotlib入門詳細教程
    與之齊名,matplotlib作為數據科學的的另一必備庫,算得上是python可視化領域的元老,更是很多高級可視化庫的底層基礎,其重要性不言而喻。本篇對matplotlib進行系統性介紹,不會面面俱到,但求體系完備、詳略得當。