1. matplotlib.pyplot工作流
pyplot 有兩個重要概念: current figure, current axes,所有的plot命令都會應用到current axes
一般pyplot
畫圖具有這樣一個流程
- 創建一個當前畫板 plt.figure(1), 1為畫板的編號,可以不填,這一步驟也可以省略, 直接執行第2步后台會自動執行這一步
- plt.subplot(221) 將當前畫板分為4個繪畫區域(axes),221表示將畫板分為2行2列,並在第一個畫板繪圖
- plt.plot(x,y,...) 繪圖,並制定 line 的屬性和圖例
- plt.xlabel('x') 等 配置坐標軸
- plt.show() 顯示圖片
import matplotlib.pyplot as plt
import numpy as np
plt.figure(1, figsize=(4,4))
# 只傳入一個參數的話, 默認為y軸, x軸默認為range(n)
# axis()指定坐標軸的取值范圍 [xmin, xmax, ymin, ymax], 注意傳入的是一個列表即:axis([])
plt.subplot(211)
plt.axis([-1, 4, -1, 5])
plt.plot([1,2,3])
plt.title("plt.plot([1,2,3])")
# ro 表示點的顏色和形狀, 默認為 'b-'
plt.subplot(212)
plt.axis([-1, 4, -1, 5])
plt.plot([1,2,3], 'ro')
plt.title("plt.plot([1,2,3],'ro')")
plt.figure(2, figsize=(4,4))
# plot可以一步畫出多條線,不過沒法設置其他的line properties
plt.axis([0, 6, 0, 20])
x = np.arange(0, 4, 0.08)
plt.plot(x, x, 'r--', x, np.power(x,2), 'bs',x, np.power(x,3), 'g^')
plt.show()


2. 設置 曲線屬性
繪圖中的line有很多屬性 ,這里有很多方式設置line properties
-
關鍵字 如:
linewidth
plt.plot(x, y, 'linewidth'=2.0)
-
使用 matplotlib.line.Line2D 的set方法, plt.plot() 會返回 matplotlib.line.Line2D對象元組 如
line1, line2 = plot(x1, y1, x2 ,y2)
-
使用pyplot.setp()方法(set properties), 該方法透明處理單個對象和一組對象(見例子)
import matplotlib.pyplot as plt
import numpy as np
#2
x = np.arange(0, 4, 0.2)
# 返回的是一個元組, 通過 line, 取得元組的第一個元素
line, = plt.plot(x, y, 'g-')
#關閉抗鋸齒, 可以看到輸出的圖像與之前比起來不是那么平滑
line.set_antialiased(False)
#3
line1, line2 = plot(x1, y1, x2 ,y2)
plt.setp(lines, color='r', 'linewidth'=2.0)
lines = plt.plot([1, 2, 3])
# 為了得到可設置的 line properties,
plt.setp(lines)
# 如果你只想知道某一個屬性的有用取值, 如下(屬性要用''括起來)
plt.setp(lines, 'linestyle')
3.同時在多個figure和axes上繪圖
pyplot 有兩個重要概念: current figure, current axes
所有的plot命令都會應用到 current axes
plt.gca(): 返回當前axes(matplotlib.axes.Axes)
plt.gcf(): 返回當前figure(matplotlib.figure.Figure)
plt.clf(): 清理當前figure
plt.cla(): 清理當前axes
plt.close(): 一副figure知道顯示的調用close()時才會釋放她所占用的資源;
如果你在畫很多圖,就要注意了,防止內存占用過高
#coding=utf-8
import numpy as np
import matplotlib.pyplot as plt
plt.figure(1)
# 頻譜線
def f(t):
return np.exp(-t) * np.cos(2*np.pi*t)
t0 = np.arange(0.0, 5.0, 0.04)
t1 = np.arange(0.0, 5.0, 0.2)
plt.subplot(211)
plt.plot(t1, f(t1), 'bo', t0, f(t0), 'k-')
# 心形線參數方程:x=a*(2*cos(t)-cos(2*t)), y=a*(2*sin(t)-sin(2*t))
t2 = np.arange(0.0, 2*np.pi, np.pi/20)
x = 2*np.cos(t2)-np.cos(2*t2)
y = 2*np.sin(t2) - np.sin(2*t2)
plt.subplot(212)
plt.axis([-4, 3, -5, 5])
plt.plot(x/2, y, 'r--', label="cardioid")
plt.legend(loc="upper left", );
plt.show()

_
4. 給axes添加文本說明
- plt.text()可以在任意位置添加文本, 而plt.xlabel(), plt.ylabel, plt.title()是將文本放在指定位置
plt.text(x, y, s[, fontsize, color])
: 在坐標(x,y)顯示文本s
,fontsize指定字體大小- matplotlib.text.Text 的屬性, 如同上面通過 plt.setp(line) 得到 line properties, 同樣的可以通過plt.setp(text)得到 text properties以及某個屬性的有效取值; 見 #3
- text對象中可以支持任意 TeX表達式(由2個$括起來); 見 #4
- annotating(標注) text, 用來顯示在圖形的一些特點,如極點, 最大值等,自然也是可以通過plt.setp(annoteate)獲取annotating的特性
import numpy as np
import matplotlib.pyplot as plt
#3
ax = plt.subplot(111)
t = ax.text(1, 1.5, 'text')
plt.setp(t)
plt.setp(t, 'color') # 輸出為:color: any matplotlib color
plt.setp(t, color='indigo')
#4
plt.title(r'$\sigma_i=15$') # 即σi
#5
x = np.arange(0, 5, 0.02)
y = np.cos(2*np.pi*x)
plt.plot(x, y, lw=2.0)
plt.ylim(-2,2)
# xy : 圖上需要標注的點, xytext: 對標記點進行說明的文本
# arrowsprops: 標記方式 其中shrink為箭頭的長度(shrink越小越長)
a = plt.annotate('local max', xy=(2,1), xytext=(3,1.5),
arrowprops=dict(facecolor='k', shrink=0.02),
)

import numpy as np
import matplotlib.pyplot as plt
# Fixing random state for reproducibility
# np.random.randn 這個函數的作用就是從標准正態分布中返回一個或多個樣本值
np.random.seed(20170617)
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
p, bins, patches = plt.hist(x, 50, normed=True, facecolor='g', alpha=0.75)
plt.xlabel('Smarts', color='cyan')
plt.ylabel('Probability')
plt.title('Histogram of IQ')
plt.text(60, .025, r'$\mu=100,\ \sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True) # 顯示網格
plt.show()

5.對數以及其他非線性坐標
matplotlib.pyplot 不僅支持線性坐標, 也支持log scale, symlog scale, logit scale,改變一個坐標的刻度很簡單, 如:(scale n, 尺度,刻度)
關於這段代碼有看不懂的,可以直接翻倒下面, 有詳細的解釋
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import NullFormatter # useful for `logit` scale
# Fixing random state for reproducibility
np.random.seed(19680801)
# make up some data in the interval ]0, 1[
y = np.random.normal(loc=0.5, scale=0.4, size=1000)
y = y[(y > 0) & (y < 1)] # 選取 0<y<1 的y值
y.sort()
x = np.arange(len(y))
# plot with various axes scales
plt.figure(1)
# linear
plt.subplot(221)
plt.plot(x, y)
plt.yscale('linear')
plt.title('linear')
plt.grid(True)
# log
plt.subplot(222)
plt.plot(x, y)
plt.yscale('log')
plt.title('log')
plt.grid(True)
# symmetric log
plt.subplot(223)
plt.plot(x, y - y.mean())
plt.yscale('symlog', linthreshy=0.01)
plt.title('symlog')
plt.grid(True)
# logit
plt.subplot(224)
plt.plot(x, y)
plt.yscale('logit')
plt.title('logit')
plt.grid(True)
#使用 `NullFormatter`格式化y軸 次刻度注釋(minor tick label) 為空字符串,避免y-軸有太多tick label 而看不清
plt.gca().yaxis.set_minor_formatter(NullFormatter())
# 調整子圖布局, 應為logit可能會比普通坐標占據更多的空間(如小圖y軸tick label如"1-10^{-3}"
plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,
wspace=0.35)
plt.show()

5.1 numpy.random.normal(loc, scale, size=None),
該函數返回 高斯分布N(loc, scale)的抽樣值
loc:float
此概率分布的均值(對應着整個分布的中心centre)
scale:float
此概率分布的標准差(對應於分布的寬度,scale越大越矮胖,scale越小,越瘦高)
size:int or tuple of ints
輸出的shape,默認為None,只輸出一個值
特例: numpy.random.normal(loc=0.0, scale=1.0, size=None),
對應於numpy.random.randn(size),標准正態分布隨機抽樣
5.2 圖像figure內部各個組件內容:
title 圖像標題
Axis 坐標軸,
Label 坐標軸標注,
Tick 刻度線,
Tick Label 刻度注釋.

5.3 pyplot.subplots_adjust() 解析
plt.subplots_adjust(bottom=0.08, top=0.92, left=0.10, right=0.95, hspace=0.25, wspace=0.35)
一幅圖稱為figure, 其繪畫區域稱為axes:
bottom, top: 即 axes距離畫板底部的距離 (畫板的高度取1)
left, right: 即 axes距離畫板左邊的距離 (畫板的寬度取1)
hspace: hight space 上下axes的距離
wspace: width space 左右axse的距離
注: bottom, top, left, right 不管figure實際長度和寬度為多少,都會歸一化為1,這里填的數值,更確切的說是`占的比例`
import numpy as np
import matplotlib.pyplot as plt
# Fixing random state for reproducibility
t = np.arange(4)
plt.figure(figsize=(4,))
plt.subplot(221)
plt.plot(t)
plt.title("1st")
plt.subplot(222)
plt.plot(t)
plt.title("2nd")
plt.subplot(223)
plt.plot(t)
plt.title("3rd")
plt.subplot(224)
plt.plot(t)
plt.title("4th")
plt.subplots_adjust(bottom=0.1, top=0.9,
left=0.4, right=0.9,
hspace=0.1, wspace=0.1)
從下圖可以看到axes從占據figure 寬度0.4的位置開始
axes上下左右之間由於距離太近, 一些label都重疊了

# 與上圖對比, 各個參數的含義一目了然
plt.subplots_adjust(bottom=0.1, top=0.9,
left=0.1, right=0.9,
hspace=0.4, wspace=0.4)

4.4 matplotlib: log scale vs symlog scale
- log : 只允許正值
- symlog: 即 對稱log, 允許正值和賦值, 而且允許圖像在0附近取一段線性區域
import numpy
from matplotlib import pyplot
pyplot.grid(True)
xdomain = numpy.arange(-50,50, 0.1)
pyplot.plot(xdomain, xdomain)
# Plots 'sin(x)'
pyplot.plot(xdomain, numpy.sin(xdomain))
# 'linear' is the default mode, so this next line is redundant:
pyplot.xscale('linear')

# How to treat negative values?
# 1. 'mask' will treat negative values as invalid
# 2. 'mask' is the default, so the next two lines are equivalent
pyplot.xscale('log')
pyplot.xscale('log', nonposx='mask')

# How to treat negative values?
# 'mask' will treat negative values as invalid
# 'mask' is the default, so the next two lines are equivalent
pyplot.xscale('log')
pyplot.xscale('log', nonposx='mask')

# 'symlog' scaling, however, handles negative values nicely
pyplot.xscale('symlog')

# And you can even set a linear range around zero
pyplot.xscale('symlog', linthreshx=20)

# 保存figure, 默認dpi為80
pyplot.savefig('matplotlib_xscale_linear.png', dpi=50, bbox_inches='tight')
fig = pyplot.gcf()
fig.set_size_inches([4., 3.])
# figure的默認大小: [8., 6.]