matplotlib 可視化的基本原理

在平時使用matploglib的時候,將問題解決方法、使用心得、基本概念等等,都零零散散做了一些總結(jié),但是一直沒有系統(tǒng)的進行過整理。為了能夠更好的鞏固matplotlib的使用,將之前的總結(jié)進行一次系統(tǒng)化的梳理。

為什么需要數(shù)據(jù)可視化?

無論是工作,學習,生活中都會遇到各種數(shù)據(jù):年度預算數(shù)據(jù),項目人力成本數(shù)據(jù),實驗記錄數(shù)據(jù),投資收益等等。當直接面對各種數(shù)據(jù)的時候,無法直觀的反映出各種數(shù)據(jù)間的關系,因此就需要借助各種圖表來對數(shù)據(jù)進行可視化的展示。選擇合理的數(shù)據(jù)圖表,比用數(shù)據(jù)和文字描述更明了、更容易理解,將數(shù)據(jù)轉(zhuǎn)換成圖表的形式呈現(xiàn),可以幫助我們更好地了解數(shù)據(jù)之間的關聯(lián)關系及變化趨勢,對問題的研究可以做出合理的推斷和預測。
使用不同的圖表從不同的方面來闡述問題,從不同的角度表現(xiàn)相對的關系、數(shù)據(jù)與數(shù)據(jù)之間的聯(lián)系,從而尋找問題更好的解決方法。
如下圖左表格中x,y的數(shù)據(jù),單純從數(shù)據(jù)中看無法直觀的看出x,y之間的關系。但是從右圖可以很直觀的看出x,y之間為正相關。

matplotlib簡介

matplotlib使用numpy進行數(shù)組運算,并調(diào)用一系列其他的Python庫來實現(xiàn)硬件交互。matplotlib的核心是一套由對象構(gòu)成的繪圖API。它利用通用的圖形用戶界面工具包,如Tkinter, wxPython, Qt或GTK+,向應用程序嵌入式繪圖提供了應用程序接口(API)。matplotlib是基于Python語言的開源項目,旨在為Python提供一個數(shù)據(jù)繪圖包。matplotlib的對象體系嚴謹而豐富,為使用者提供了巨大的發(fā)揮空間。在熟悉了核心對象之后,可以輕易的定制圖像。matplotlib的對象體系也是計算機圖形學的一個優(yōu)秀范例。
matplotlib最初由John D. Hunter撰寫,它擁有一個活躍的開發(fā)社區(qū),并且根據(jù)BSD樣式許可證分發(fā)。 在John D. Hunter2012年去世前不久,Michael Droettboom被提名為matplotlib的主要開發(fā)者。

可以通過官網(wǎng)和源碼可以更加深入的了解matplotlib。
官網(wǎng):https://matplotlib.org
源碼:https://github.com/matplotlib/matplotlib

matplotlib 可視化的結(jié)構(gòu)

使用matplotlib繪圖,主要掌握figure(畫布)、axes(坐標系)、axis(坐標軸)之間的關系。在matplotlib中,整個圖像為一個Figure對象。在Figure對象中可以包含一個,或者多個axes對象。每個Axes對象都是一個擁有自己坐標系統(tǒng)的繪圖區(qū)域。
如下圖所示,在同一個figure畫布中,存在四個坐標系,對應的每個坐標系都有各自的坐標軸。


AxesAxisFig.png

舉個比較形象的例子,一個畫家需要創(chuàng)作一幅油畫。首先需要在畫框上固定一張畫布上,有了畫布就可以創(chuàng)作任意的作品了,這個過程就是matplotlib中初始化畫布(figure);其次,需要規(guī)劃在這個畫布上的布局,是一整幅還是多個子圖構(gòu)成?如果是多了子圖就需要為不同的的板塊分配區(qū)域了,這個區(qū)域就對應了matplotlib中為不同的子圖指定的坐標系(axes)。對應的畫布中可能會存在1個或者多個坐標系;然后,在不同的子圖創(chuàng)作完成之后,需要對邊界進行勾勒,這個邊界就對應了matplotlib中的坐標軸(axis).

matplotlib的構(gòu)成

matplotlib官網(wǎng)上提供描述其結(jié)構(gòu)的一張圖,為了更方便的了解其內(nèi)容將其中涉及到的內(nèi)容增加了中文的說明。通過這張可以大致了解到通過繪制一張圖所涵蓋的部分。通過運行后面的


AnatomyOfMatplotlib.png

相關代碼

  • matplotlib圖的構(gòu)成(圖AnatomyOfMatplotlib):

由于matplotlib對于中文顯示的支持不太好,會導致中文顯示為亂碼。對于中文字符顯示的解決方案會在后面進行說明

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import AutoMinorLocator, MultipleLocator, FuncFormatter

#支持中文
matplotlib.rcParams['font.family'] = ['Heiti TC']

np.random.seed(19680801)

X = np.linspace(0.5, 3.5, 100)
Y1 = 3+np.cos(X)
Y2 = 1+np.cos(1+X/0.75)/2
Y3 = np.random.uniform(Y1, Y2, len(X))

fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(1, 1, 1, aspect=1)


def minor_tick(x, pos):
    if not x % 1.0:
        return ""
    return "%.2f" % x

#設置x軸主刻度的位置,主刻度標簽設置為1的倍數(shù)
ax.xaxis.set_major_locator(MultipleLocator(1.000))
#設置x軸次刻度的位置,將每一個主刻度的區(qū)間等分為4格,如對應圖中第一個主刻度區(qū)間中0.25,0.50,0.75
ax.xaxis.set_minor_locator(AutoMinorLocator(4))

#設置y軸主刻度的位置,主刻度標簽設置為1的倍數(shù)
ax.yaxis.set_major_locator(MultipleLocator(1.000))
#設置y軸次刻度的位置,將每一個主刻度的區(qū)間等分為4格
ax.yaxis.set_minor_locator(AutoMinorLocator(4))

#設置x軸副刻度的文本顯示格式
ax.xaxis.set_minor_formatter(FuncFormatter(minor_tick))

#設置x軸和y軸的顯示區(qū)間
ax.set_xlim(0, 4)
ax.set_ylim(0, 4)


#設置主刻度中刻度的長寬屬性
ax.tick_params(which='major', width=1.0)
ax.tick_params(which='major', length=10)

#設置次刻度的文本大小,顏色
ax.tick_params(which='minor', width=1.0, labelsize=10)
ax.tick_params(which='minor', length=5, labelsize=10, labelcolor='0.25')

#顯示網(wǎng)格設置
ax.grid(linestyle="--", linewidth=0.5, color='.25', zorder=-10)

#按照y1,y2,y3來繪制
ax.plot(X, Y1, c=(0.25, 0.25, 1.00), lw=2, label="Blue signal", zorder=10)
ax.plot(X, Y2, c=(1.00, 0.25, 0.25), lw=2, label="Red signal")
ax.plot(X, Y3, linewidth=0,
        marker='o', markerfacecolor='w', markeredgecolor='k')

#設置圖的標題
ax.set_title("Anatomy of a figure", fontsize=20, verticalalignment='bottom')
#設置x軸lable
ax.set_xlabel("X axis label")
#設置y軸lable
ax.set_ylabel("Y axis label")

#設置圖例
ax.legend()


#通過patches和patheffects中的函數(shù)來繪制對應圖中圓圈標注的地方
def circle(x, y, radius=0.15):
    from matplotlib.patches import Circle
    from matplotlib.patheffects import withStroke
    circle = Circle((x, y), radius, clip_on=False, zorder=10, linewidth=1,
                    edgecolor='black', facecolor=(0, 0, 0, .0125),
                    path_effects=[withStroke(linewidth=5, foreground='w')])
    ax.add_artist(circle)

#設置文本顯示的屬性
def text(x, y, text):
    ax.text(x, y, text, backgroundcolor="white",
            ha='center', va='top', weight='bold', color='blue')


#對各個標注點的顯示
# Minor tick
circle(0.50, -0.10)
text(0.50, -0.32, "次刻度標簽(Minor tick label)")

# Major tick
circle(-0.03, 4.00)
text(0.03, 3.80, "主刻度(Major tick)")

# Minor tick
circle(0.00, 3.50)
text(0.00, 3.30, "次刻度(Minor tick)")

# Major tick label
circle(-0.15, 3.00)
text(-0.15, 2.80, "主刻度標簽(Major tick label)")

# X Label
circle(1.80, -0.27)
text(1.80, -0.45, "x軸標簽(X axis label)")

# Y Label
circle(-0.27, 1.80)
text(-0.27, 1.6, "y軸標簽(Y axis label)")

# Title
circle(1.60, 4.13)
text(1.60, 3.93, "名稱(Title)")

# Blue plot
circle(1.75, 2.80)
text(1.75, 2.60, "線條(Line)\n(line plot)")

# Red plot
circle(1.20, 0.60)
text(1.20, 0.40, "線條(Line)\n(line plot)")

# Scatter plot
circle(3.20, 1.75)
text(3.20, 1.55, "節(jié)點樣式(Markers)\n(scatter plot)")

# Grid
circle(3.00, 3.00)
text(3.00, 2.80, "網(wǎng)格(Grid)")

# Legend
circle(3.70, 3.80)
text(3.70, 3.60, "圖例(Legend)")

# Axes
circle(0.5, 0.5)
text(0.5, 0.3, "坐標系(Axes)")

# Figure
circle(-0.3, 0.65)
text(-0.3, 0.45, "畫布(Figure)")

color = 'blue'

#注解的顯示,圖中右下角spines
ax.annotate('坐標軸(Spines)', xy=(4.0, 0.35), xytext=(3.3, 0.5),
            weight='bold', color=color,
            arrowprops=dict(arrowstyle='->',
                            connectionstyle="arc3",
                            color=color))

ax.annotate('', xy=(3.15, 0.0), xytext=(3.45, 0.45),
            weight='bold', color=color,
            arrowprops=dict(arrowstyle='->',
                            connectionstyle="arc3",
                            color=color))

#文本的顯示
ax.text(4.0, -0.4, "參考自官網(wǎng)的簡介(\nMade with http://matplotlib.org)",
        fontsize=10, ha="right", color='.5')


#fig.savefig('./img/AnatomyOfMatplotlib.png')
plt.show()
  • 多子圖顯示(圖AxesAxisFig):
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0.0,6.0)

figure,ax=plt.subplots(2,2,figsize=(16,9))

ax[0][0].plot(x,np.sin(np.pi*x));
ax[0][0].set_title("正弦")
ax[0][0].set_xlabel("時間")
ax[0][0].set_ylabel("幅度")
ax[0][0].set_ylabel("幅度")

ax[0][1].plot(x,np.cos(np.pi*x));
ax[0][1].set_title("余弦")
ax[0][1].set_xlabel("時間")
ax[0][1].set_ylabel("幅度")

ax[1][0].plot(x,np.log((x+1)*10));
ax[1][0].set_title("指數(shù)")
ax[1][0].set_xlabel("時間")
ax[1][0].set_ylabel("距離")


ax[1][1].plot(x,x*4);
ax[1][1].set_title("投資")
ax[1][1].set_xlabel("資金")
ax[1][1].set_ylabel("收益")

figure.tight_layout(pad=1.5)
#figure.savefig('./img/Subplots.png')
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容