Python绘图工具包:matplotlib

1. 目的

了解matplotlib

  • 注意:
    • python自带交互环境, plt.show(), 点击关闭后,可以继续编写代码
    • ipython交互环境,plt.show(), 点击关闭后,plt.show没有退出,无法执行
    • ipython notebook, 如果要在浏览器中显示绘图结果,需要在首行添加: %matplotlib inline ,然后在编写代码

2. 过程

2.1 函数

2.1.1 plot

  • plot(*args, **kwargs) :主要参数见源码;
  • *args : 即: 输入单变量,如,x轴数据和y轴数据, 图标属性信息
  • *kwargs : 即: 参数为kv格式, 如, label=**, linewidth=
  • 例子:
    • plt.plot("a", "b", 'go-', data={"a": [1, 2, 3], "b": [4, 5, 6]}, label='line 1')
    • plt.plot([1, 2, 3], [1, 2, 3], 'go-', label='line 1', linewidth=2)

2.1.2 plt.axvline

  • 绘制垂直x轴的直线
  • 实例
>>> import numpy as np;import matplotlib.pyplot as plt
>>> d1 = np.arange(0, 10, 1)
>>> d1
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> for k,v in zip(d1[:-1], d1[1:]):
...     plt.axvline(.5 * (k+v), color='b')
... 
<matplotlib.lines.Line2D object at 0x7f18735bff90>
<matplotlib.lines.Line2D object at 0x7f18735cc610>
<matplotlib.lines.Line2D object at 0x7f18735ccb50>
<matplotlib.lines.Line2D object at 0x7f18735ccf50>
<matplotlib.lines.Line2D object at 0x7f18735d6550>
<matplotlib.lines.Line2D object at 0x7f18735d6a10>
<matplotlib.lines.Line2D object at 0x7f18735d6ed0>
<matplotlib.lines.Line2D object at 0x7f18735e43d0>
<matplotlib.lines.Line2D object at 0x7f18735e4890>
>>> plt.show()
axvline绘制直线

2.2 实例

折线图

直线: 先上例子

import matplotlib.pyplot as plt 
plt.plot([0,1,2,3,4])  # 方式1:list参数,默认为y值,自动生成x轴值
# plt.plot([0,1,2,3,4], [1,4,32,16])  # 方式2:list参数,传入x和y值, 
plt.ylabel('some numbers')
plt.xlabel('any numbers')
plt.show()

直线: 配置画布

  • 选择显示模式
import matplotlib.pyplot as plt
plt.plot([1,2,3,4], [1,4,9,16], 'ro')
plt.axis([0, 6, 0, 20])
plt.show()
  • 显示多个线
import numpy as np
import matplotlib.pyplot as plt

# evenly sampled time at 200ms intervals
t = np.arange(0., 5., 0.2)

# red dashes, blue squares and green triangles
# 注意: plot 输入的参数,即使是
plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^') 
plt.show()
  • 设置属性: 用key-value格式
import matplotlib.pyplot as plt
x = range(10)
y = range(5,55,5)
plt.plot(x,y, '-', linewidth=2.0)
plt.show()
  • 设置属性: 用setp()函数
import matplotlib.pyplot as plt
x1 = range(10)
y1 = range(5,55,5)

x2 = range(3,33,3)
y2 = range(2,22,2)

lines = plt.plot(x1, y1, x2, y2)
# use keyword args
plt.setp(lines, color='r', linewidth=2.0)
# or MATLAB style string value pairs
plt.setp(lines, 'color', 'r', 'linewidth', 2.0)
plt.show()

正弦曲线: 多画布

import numpy as np
import matplotlib.pyplot as plt 
def f(t):
    return np.exp(-t) * np.cos(2*np.pi*t)

t1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.05)

plt.figure(1)
# 默认: 如果画布数plot小于10,且画布的行row和列column也小于10,可以用数值代替
# 例如: plt.subplot(312) 表示plot_number=3, row=1, column=2
plt.subplot(311)   
# plt.plot(t1, f(t1), 'o' ,t2, f(t2), 'o')
plt.plot(t2, f(t2), 'o')

plt.subplot(312)
# plt.plot(t2, np.cos(2*np.pi*t2), 'r--')
plt.plot(t1, f(t1), 'o' )

plt.subplot(313)
# plt.plot(t2, np.cos(2*np.pi*t2), 'r--')
plt.plot(t1, f(t1), 'o' )

plt.show()

标签显示

#生成长度为10,在[0,1)之间平均分布的随机数组:
numpy.random.random(size=10)

#生成在-0.1到0.1之间的平均分布:
# 方法1:
0.2*numpy.random.random(size=10)-0.1
# 方法2:
numpy.random.uniform(-0.1,0.1,size=10)

#生成长度为10,符合正态分布的随机数
mu,sigma=0,0.1 #均值与标准差
rarray=numpy.random.normal(mu,sigma,10)
  • 标签的添加
import numpy as np
import matplotlib.pyplot as plt

# 随机种子,目的: 随机可重现
np.random.seed(19680801)

# 产生均值100, 均方差15的随机数
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

# 直方图
n, bins, patches = plt.hist(x, 50, normed=1, facecolor='g', alpha=0.75)


# 添加轴标签 
# 注意:不能显示中文
plt.xlabel("I am x axes")
# plt.xlabel('I am x axes', fontsize=14, color='red') # 试试修改标签的属性
plt.ylabel("I am y axes")
plt.title('XX histogram, The name must English, Not Chinese')

# 添加文字标签
plt.text(60, 0.025, r'$\mu=100,  \sigma=15, $')
plt.axis([40,160, 0, 0.03])

# 显示栅格
plt.grid(True)
plt.show()
  • 添加注解:Annotating
import numpy as np
import matplotlib.pylab as plt

ax = plt.subplot(111)

t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)
line, = plt.plot(t, s, lw=2)

# xy:
plt.annotate('local max', xy=(2,1) , xytext=(1, 1.5), arrowprops=dict(facecolor='black', shrink=0.1), )

plt.ylim(-2,2)
plt.show()

非线性图

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)]
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
# 注意版本,1.3没有logit,后来安装2.1.0rc1后可以正常显示logit的图
plt.subplot(224)
plt.plot(x, y)
plt.yscale('logit')
plt.title('logit')
plt.grid(True)
# Format the minor tick labels of the y-axis into empty strings with
# `NullFormatter`, to avoid cumbering the axis with too many labels.
plt.gca().yaxis.set_minor_formatter(NullFormatter())
# Adjust the subplot layout, because the logit one may take more space
# than usual, due to y-tick labels like "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()

子图的布局

  • 拼图模式
import matplotlib.pyplot as plt
ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3) # 生成3x3的格子,第一行,1个子图,宽度占满3格
ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2) # 第二行,第一个子图,宽度占2格
ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2) # 第二行,第二个子图,宽度默认占1格,高度占2格
ax4 = plt.subplot2grid((3, 3), (2, 0))
ax5 = plt.subplot2grid((3, 3), (2, 1))
plt.show()

# 等效下面代码
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(3, 3)
ax1 = plt.subplot(gs[0, :])
ax2 = plt.subplot(gs[1, :-1])
ax3 = plt.subplot(gs[1:, -1])
ax4 = plt.subplot(gs[-1, 0])
ax5 = plt.subplot(gs[-1, -2])

# 也可以直接定义,长款
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(2, 2,
                       width_ratios=[1, 2],
                       height_ratios=[4, 1]
                       )  # 相当于把豆腐宽度切了左边三分之一,然后下部五分之一再切一刀

ax1 = plt.subplot(gs[0])
ax2 = plt.subplot(gs[1])
ax3 = plt.subplot(gs[2])
ax4 = plt.subplot(gs[3])

  • 多格显示单图

'''
import matplotlib.pyplot as plt
ax = plt.subplot2grid((2, 2), (0, 0)) # 创建2x2格子,单只显示左上角格子
plt.show()

等效于下面代码

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(2, 2)
ax = plt.subplot(gs[0, 0])
plt.show()
'''

多个子图的标签: 不重叠

import matplotlib.pyplot as plt
plt.rcParams['savefig.facecolor'] = "0.8"   

def example_plot(ax, fontsize=12):
     ax.plot([1, 2])
     ax.locator_params(nbins=10)
     ax.set_xlabel('x-label', fontsize=fontsize)
     ax.set_ylabel('y-label', fontsize=fontsize)
     ax.set_title('Title', fontsize=fontsize)


plt.close('all')
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2)
example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
example_plot(ax4)
#如下代码,加上后,就不会产生便签重叠
plt.tight_layout()
# plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0)
plt.show()
  • 多图空间布局
plt.close('all')
fig = plt.figure()

import matplotlib.gridspec as gridspec
def example_plot(ax, fontsize=12):
     ax.plot([1, 2])
     ax.locator_params(nbins=10)
     ax.set_xlabel('x-label', fontsize=fontsize)
     ax.set_ylabel('y-label', fontsize=fontsize)
     ax.set_title('Title', fontsize=fontsize)


gs1 = gridspec.GridSpec(2, 1)
ax1 = fig.add_subplot(gs1[0])
ax2 = fig.add_subplot(gs1[1])
# ax3 = fig.add_subplot(gs1[2])

example_plot(ax1)
example_plot(ax2)
# example_plot(ax3)

# gs1在画布的位置,由rect定义, 两个点确定一个矩形, 即定义画布的左半边,归gs1显示
# 点1 (0,0) : 左上角位置
# 点2 (0.5,1) : 底部中间位置
gs1.tight_layout(fig, rect=[0, 0, 0.5, 1])  

gs2 = gridspec.GridSpec(3, 1)

for ss in gs2:
    ax = fig.add_subplot(ss)
    example_plot(ax)
    ax.set_title("")
    ax.set_xlabel("")

ax.set_xlabel("x-label", fontsize=12)

# gs2在画布的位置,由rect定义, 两个点确定一个矩形, 即定义画布的左半边,归gs2显示
gs2.tight_layout(fig, rect=[0.5, 0, 1, 1], h_pad=0.5)


plt.show()


多图空间布局

matplotlib中级进阶:艺术家教程

matplotlib结构

  • matplotlib.backend_bases.FigureCanvas : 画布, 图片绘制区域

  • matplotlib.backend_bases.Renderer : 渲染对象,绘制到画布的元素

  • matplotlib.artist.Artist : 用渲染对象,画在画布上,包括布局,标签,线等

  • Subplot is just a subclass of Axes : subplot 是 Axes的子类

渲染对象的控制

import numpy as np
import matplotlib.pyplot as plt

# plt.figure creates a matplotlib.figure.Figure instance
fig = plt.figure()
rect = fig.patch # a rectangle instance
rect.set_facecolor('lightgoldenrodyellow')

ax1 = fig.add_axes([0.1, 0.3, 0.4, 0.4])
rect = ax1.patch
rect.set_facecolor('lightslategray')


for label in ax1.xaxis.get_ticklabels():
    # label is a Text instance
    label.set_color('red')
    label.set_rotation(45)   # 标签旋转角度
    label.set_fontsize(16)   # 标签字体大小

for line in ax1.yaxis.get_ticklines():
    # line is a Line2D instance
    line.set_color('green')
    line.set_markersize(25)  # 单位分割线的长度
    line.set_markeredgewidth(3)

plt.show()
渲染对象的控制
  • 坐标轴格式化
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

# Fixing random state for reproducibility
np.random.seed(19680801)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(100*np.random.rand(20))

formatter = ticker.FormatStrFormatter('$%1.2f')
ax.yaxis.set_major_formatter(formatter)

for tick in ax.yaxis.get_major_ticks():
    tick.label1On = True  # 左边坐标轴
    tick.label2On = True  # 右边坐标轴
    tick.label2.set_color('green')

plt.show()
坐标轴格式化

图例 : 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()

  • 图例:实例1
import matplotlib.pyplot as plt


plt.subplot(211)
plt.plot([1,2,3], label="test1")
plt.plot([3,2,1], label="test2")
# Place a legend above this subplot, expanding itself to
# fully use the given bounding box.
plt.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=3,
           ncol=2, mode="expand", borderaxespad=0.)

plt.subplot(223)
plt.plot([1,2,3], label="test1")
plt.plot([3,2,1], label="test2")
# Place a legend to the right of this smaller subplot.
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)  # loc代表图例的位置

plt.show()
图例:实例1
  • 图例:实例2
import numpy as np
import matplotlib.pyplot as plt
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels)

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'])  # legend 接受kv格式

plt.show()
图例 : 实例2
  • 图例:实例3
import matplotlib.pyplot as plt

line1, = plt.plot([1,2,3], label="Line 1", linestyle='--')
line2, = plt.plot([3,2,1], label="Line 2", linewidth=4)

# Create a legend for the first line.
# first_legend = plt.legend(handles=[line1], loc=1) # 这种方式在 matplotlib 1.3.1 会报错, 升级到2.0.2就没问题了
first_legend = plt.legend([line1],["AAA"], loc=1)

# Add the legend manually to the current Axes.
ax = plt.gca().add_artist(first_legend)

# Create another legend for the second line.
plt.legend([line2],["BBB"], loc=4)

plt.show()

图例:实例3
  • 点折线:实例4
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerLine2D

line1, = plt.plot([3,2,1], marker='o', label='Line 1')
line2, = plt.plot([1,2,3], marker='o', label='Line 2')

plt.legend(handler_map={line1: HandlerLine2D(numpoints=4)})  # 点数目,如果大于样本数,会出现两个线图标, 可以尝试修改numpoints值
plt.show()
  • 图标叠加:实例5
import matplotlib.pyplot as plt
from numpy.random import randn

z = randn(10)

red_dot, = plt.plot(z, "ro", markersize=15)
# Put a white cross over some of the data.
white_cross, = plt.plot(z[:5], "w+", markeredgewidth=3, markersize=15)

plt.legend([red_dot, (red_dot, white_cross)], ["Attr A", "Attr A+B"])  # 图标叠加,kv格式
Paste_Image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容