matplotlib

matplotlib基础

matplotlib是面向对象的绘图工具包,绘制的图形中的每一个元素都是一个对象,可以修改这些对象的属性,从而改变图样式。

matplotlib中主要绘图对象列表如下:

  • Figure对象,可以想象为一张画布;
  • Axes对象,字面理解为坐标轴也可以认为时子图,在一个Figure对象中可以包含多个Axes对象,也就是说一张画布可以包含多个子图;* Line2D对象,代表线条;
  • Text对象,代表了文字;

虽然matplotlib是面向对象的绘图工具包,但是也提供了一些常用的绘图方法,可以直接调用plt模块相关方法就可以完成绘图需求,这是因为plt模块内部保存了当前的Figure对象信息,当使用plt的相关方法绘图时,底层实际调用了当前Figure对象的相关方法。可以通过plt.gcf()和plt.gca()分别获取当前用于绘图的Figure和Axes对象。

通过plt.figure()创建一个新的Figure对象,然后在此Figure对象上创建Axies对象:

In [1]: import numpy as np

In [2]: import matplotlib.pyplot as plt

In [3]: fig1 = plt.figure()

In [4]: ax1 = fig1.add_subplot(1, 1, 1)

In [5]: fig1
Out[5]: <matplotlib.figure.Figure at 0x2b4d0bdf4e0>

In [6]: plt.gcf()
Out[6]: <matplotlib.figure.Figure at 0x2b4d0bdf4e0>

In [7]: ax1
Out[7]: <matplotlib.axes._subplots.AxesSubplot at 0x2b4d0bff780>
In [9]: plt.gca()
Out[9]: <matplotlib.axes._subplots.AxesSubplot at 0x2b4d0bff780>

In [10]: fig2 = plt.figure()

In [11]: ax2 = fig2.add_subplot(1, 1, 1)

In [12]: fig2
Out[12]: <matplotlib.figure.Figure at 0x2b4d0f602e8>

In [13]: plt.gcf()
Out[13]: <matplotlib.figure.Figure at 0x2b4d0f602e8>

In [14]: ax2
Out[14]: <matplotlib.axes._subplots.AxesSubplot at 0x2b4d0f882e8>

In [15]: plt.gca()
Out[15]: <matplotlib.axes._subplots.AxesSubplot at 0x2b4d0f882e8>

每当创建新的Figure对象时,plt.gcf()获取到的当前的Figure对象也变成了新创建的Figure对象,因为它们的内存地址相同。fig1.add_subplot(1, 1, 1)方法,用于在Figure对象上创建一个新的Axes对象,由于Figure可以包含多个Axes对象,所以这里的参数含义是说,添加一个Axes对象到布局为一行一列的第一个位置上。
在Figure对象上插入四个Axes对象,布局为两行两列:

In [16]: fig = plt.figure()

In [17]: ax1 = fig.add_subplot(2, 2, 1)

In [18]: ax2 = fig.add_subplot(2, 2, 2)

In [19]: ax3 = fig.add_subplot(2, 2, 3)

In [20]: ax1.plot(np.random.randn(50).cumsum(), 'k--')
Out[20]: [<matplotlib.lines.Line2D at 0x2b4d1ab5550>]

In [21]: _ = ax2.hist(np.random.randn(100), bins=20, color='k')

In [22]: ax3.scatter(np.arange(30), np.arange(30) + 3 * np.random.randn(30))
Out[22]: <matplotlib.collections.PathCollection at 0x2b4d1b1f9b0>

In [23]: fig.show()

以上代码,首先创建一个Figure对象,然后插入3个Axes对象,接着分别在Axes对象上绘制了累积和线图,直方图以及散点图,最后通过fig.show()方法显示出图形如下:


Figure_1.png

常用属性设置

matplotlib绘制的图形可以设置各种属性,如坐标系的刻度,标题,标签等属性。

In [24]: fig = plt.figure()

In [25]: ax = fig.add_subplot(1, 1, 1)

In [26]: # 设置标题

In [27]: ax.set_title("Axes Example")
Out[27]: Text(0.5,1,'Axes Example')

In [28]: major_ticks = np.arange(0, 101, 20)

In [29]: minor_ticks = np.arange(0, 101, 5)

In [30]: # 设置刻度

In [31]: ax.set_xticks(major_ticks)
In [33]: ax.set_xticks(minor_ticks, minor=True)
In [34]: ax.set_yticks(major_ticks)
In [35]: ax.set_yticks(minor_ticks, minor=True)
In [36]: # 设置X, Y轴标签

In [37]: ax.set_xlabel("X axis")
Out[37]: Text(0.5,0,'X axis')

In [38]: ax.set_ylabel("Y axis")
Out[38]: Text(0,0.5,'Y axis')

In [39]: # 设备网格
In [41]: ax.grid(which='minor', alpha=0.2)

In [42]: ax.grid(which='major', alpha=0.5)

In [43]: # 添加文字

In [44]: ax.text(42.5, 50, "shiyanlou")
Out[44]: Text(42.5,50,'shiyanlou')

In [45]: fig.show()

执行以上代码,绘制的图形如下:


Figure_2.png

以上代码首先创建了一个Figure对象,接着创建了唯一一个Axes对象,后续的所有属性都基于该Axes对象设置:

  • ax.set_title 设置图形的标题;
  • ax.set_xticks 设置X轴的刻度,其中minor=True参数表示设置更小的刻度;
  • ax.set_yticks 设置Y轴的刻度;
  • ax.set_xlabel 设置X轴的标签;
  • ax.set_ylabel 设置X轴的标签;
  • ax.grid 开启图形的刻度网格,其中minor=True参数表示显示小刻度的网格;
  • ax.text 为图形添加文字,前两个参数表示添加的文字在坐标系中的位置;

绘制曲线的颜色,设置图例,代码如下:

In [46]: x = np.linspace(0, 1, 100)

In [47]: fig = plt.figure()

In [48]: ax = fig.add_subplot(1, 1, 1)

In [49]: ax.set_title("shiyanlou")
Out[49]: Text(0.5,1,'shiyanlou')

In [50]: ax.plot(x, x ** (1/8), 'b--', label=r'$y = x^{1/8}$')
Out[50]: [<matplotlib.lines.Line2D at 0x2b4d1453908>]

In [51]: ax.plot(x, x ** 8, 'r--', label=r'$y = x^{8}$')
Out[51]: [<matplotlib.lines.Line2D at 0x2b4d1453f98>]

In [52]: ax.plot(x, x ** (1/2), 'r.', label=r'$y = x^{1/2}$')
Out[52]: [<matplotlib.lines.Line2D at 0x2b4d146c358>]

In [53]: ax.plot(x, x ** 2, 'b.', label=r'$y = x^{2}$')
Out[53]: [<matplotlib.lines.Line2D at 0x2b4d1453588>]

In [54]: ax.plot(x, x, 'g-', label=r'$y = x$')
Out[54]: [<matplotlib.lines.Line2D at 0x2b4d1453e48>]

In [55]: ax.legend()
Out[55]: <matplotlib.legend.Legend at 0x2b4d1453128>

In [56]: ax.axis([0, 1, 0, 1])
Out[56]: [0, 1, 0, 1]
In [58]: fig.show()

图形显示如下:


Figure_3.png

在上面的代码中,通过 np.linspace(0, 1, 100) 创建了 100 个值,这些值平均分布在 0 到 1 的范围内。接着我们在 Axes 对象上绘制了 5 条曲线,这 5 条曲线分别对应于 5 个函数,函数名称已经通过图例的形式显示在图形上了。

其中,我们使用类似于 ax.plot(x, x ** (1/8), 'b--', label=r'y = x^{1/8}y=x
1/8
') 方法绘制曲线,该方法有四个参数,前两个参数分别对应于 X, Y 轴的数据,绘图时会根据 x 和 x ** (1/8) 值序列确定曲线的位置。第三个参数 b-- 代表绘制的曲线是 blue 蓝色,样式是虚线。matplotlib 中有多种指定线条颜色和样式的办法,如 r-- 指明红色虚线,r. 代表红色点,更多的样式可以参考 matplotlib 文档。最后一个参数 label=r'y = x^{1/8}y=x
1/8
') 设置了线条的标签,该标签文字内容是数学公式,matplotlib 支持 LaTeX 语法显示各种数学公式。

有的时候,我们想在图形上显示曲线标签信息,这个时候可以使用 ax.legend() 方法,该方法使用曲线的标签信息(也就是绘制曲线是传入的 label 参数)自动生成图例,并将图例放到图形合适的位置。

最后为了方便查看图形,我们将图形的视口坐标设置成了 [0, 1, 0, 1] ,代表X, Y坐标轴范围都设置为 0 到 1。如果图形显示范围超过了 0 到 1 的范围,则会自动截取 0 到 1 范围内的图形进行显示。

matplotlib 绘图时可以设置很多属性,比如设置注解,设置外部图片等,这些都可以通过调用 Axes 对象相应方法进行,更多的用法可以查看 Axes 对象 API 文档。

常用图形

线形图

线性图更多时候是用来观察变量之间的函数关系,如果满足y = 2x的线性关系,那么绘制的图形是一条直线,如果没关系,则是一堆涂鸦。
使用Axes.plot方法绘制线形图:

In [78]: fig1 = plt.figure()

In [79]: ax1 = fig1.add_subplot(1, 1, 1)

In [80]: x = np.random.randn(100)

In [81]: y = np.random.randn(100)
In [83]: ax1.plot(x, y)
Out[83]: [<matplotlib.lines.Line2D at 0x2b4d2a6ba58>]

In [84]: fig1.show()

以上代码创建了两个随机的数值序列,这两个数值序列之间理论上没有任何关系,显示的图形如下:


Figure_4.png

直方图

直方图可以显示数据分布情况,X 轴一般是统计的样本,而 Y 是样本对应的统计度量。为了构建直方图,第一步是将值的范围分段,即将整个值的范围分成一系列间隔,然后计算每个间隔中有多少值。 这些值通常被指定为连续的,不重叠的变量间隔。 间隔必须相邻,并且通常是(但不是必须的)相等的大小。在 matplotlib 中可以使用 Axes.hist 方法绘制直方图:

In [85]: fig2 = plt.figure()

In [86]: ax2 = fig2.add_subplot(1, 1, 1)

In [87]: data = np.random.normal(0, 20, 1000)

In [88]: bins = np.arange(-100, 100, 5)
In [90]: ax2.hist(data, bins=bins)
Out[90]:
(array([   0.,    0.,    0.,    0.,    0.,    1.,    0.,    2.,    2.,
           4.,    8.,    9.,   14.,   30.,   39.,   60.,   73.,   83.,
          88.,  100.,   80.,  103.,   75.,   69.,   58.,   44.,   25.,
           7.,   12.,    7.,    4.,    0.,    2.,    1.,    0.,    0.,
           0.,    0.,    0.]),
 array([-100,  -95,  -90,  -85,  -80,  -75,  -70,  -65,  -60,  -55,  -50,
         -45,  -40,  -35,  -30,  -25,  -20,  -15,  -10,   -5,    0,    5,
          10,   15,   20,   25,   30,   35,   40,   45,   50,   55,   60,
          65,   70,   75,   80,   85,   90,   95]),
 <a list of 39 Patch objects>)

In [91]: fig2.show()

上面的代码首先通过 np.random.normal 方法,在 0 到 20 的范围产生 1000 个符合正态分布的数据值,然后通过 np.arange(-100, 100, 5) 创建了 X 轴的区间刻度。创建的图形类似下图:


Figure_5.png

散点图

散点图,将所有的数据值在图形中绘制成点,这样有多少数据值在图形中就会有多少个点。通过这些数据点可以看出数据值的分布模式,比如是否有聚类模式,或者相关关系或者发现离群点。在 matplotlib 中可以通过 Axes.scatter 绘制散点图:

In [92]: fig3 = plt.figure()

In [93]: ax3 = fig3.add_subplot(1, 1, 1)

In [94]: x = np.arange(1, 101)

In [95]: y = 20 + 3 * x + np.random.normal(0, 60, 100)

In [96]: ax3.scatter(x, y)
Out[96]: <matplotlib.collections.PathCollection at 0x2b4d4747198>

In [97]: fig3.show()

为了模拟散点图,先通过 np.arange(1, 101) 创建了 100 个数据值,接着基于此创建了 100 个 Y 轴数据,可以看到这里两组数据值之间有相关关系,因为是基于线性关系然后加上随机数生成的,绘制的散点图也证明了这点(图形向上倾斜):

Figure_6.png

箱线图

箱线图可以看出数据的分散程度,异常值等信息,箱线图根据一组数据的以下5个统计值进行绘制:

  • 最小值
  • 第1四分位数
  • 中位数
  • 第3四分位数
  • 最大值

其中四分位数,是指将一组数据值按大小排序后分成四等分,每一部分包含 1/4 的数据,这种划分的分割点就是四分位数。其中第1部分和第2部分的分割点称为第1分位数Q 1, 也被称为第25百分位数,第3部分和第4部分的分割点称为第3四分位数 Q 3,也被称为第75百分位数。而第二部分和第三部分的分割点是第2四分数,也就是中位数。其中四分位距 IQRIQR 是指第三四分位数和第一分四分位数的差,也就是IQR=Q 3−Q 1。四分位距反映了中间 50% 数据的离散程度,数值越小代表数据越集中,越大代表数据越分散。

在 matplotlib 中可以使用 Axes.boxplot 方法绘制箱线图:

In [98]: fig4 = plt.figure()

In [99]: ax4 = fig4.add_subplot(1, 1, 1)

In [100]: # 产生50个小于100的随机数

In [101]: spread = np.random.rand(50) * 100

In [102]: # 产生25个值为50的数据

In [103]: center = np.ones(25) * 50

In [104]: # 异常值

In [105]: outlier_high = np.random.rand(10) * 100 +100

In [106]: outlier_low = np.random.rand(10) * -100

In [107]: data = np.concatenate((spread, center, outlier_high, outlier_low), 0)

In [108]: ax4.boxplot(data)
Out[108]:
{'boxes': [<matplotlib.lines.Line2D at 0x2b4d507eb70>],
 'caps': [<matplotlib.lines.Line2D at 0x2b4d5087438>,
  <matplotlib.lines.Line2D at 0x2b4d508e828>],
 'fliers': [<matplotlib.lines.Line2D at 0x2b4d508ef28>],
 'means': [],
 'medians': [<matplotlib.lines.Line2D at 0x2b4d508eb00>],
 'whiskers': [<matplotlib.lines.Line2D at 0x2b4d507ec18>,
  <matplotlib.lines.Line2D at 0x2b4d5087668>]}

In [109]: fig4.show()

上面代码中,我们特意创建data数据,可以推断出该数据的中位数是50,还有一些其他异常值,绘制图形如下:


Figure_7.png

Pandas绘图

Pandas高度整合了matplotlib,可以直接调用DataFrame对象的某些方法进行绘图,更加方便的时候DataFrame的标签信息会自动绘制到图形上。

直接在Series对象上绘制线型图,代码如下:


Figure_8.png

在DataFrame对象上绘制箱线图:

In [117]: df = pd.DataFrame(np.random.rand(5, 4), columns=['A', 'B', 'C', 'D'])

In [118]: df.boxplot()
Out[118]: <matplotlib.axes._subplots.AxesSubplot at 0x2b4d8f7a4e0>

In [119]: plt.show()
Figure_9.png

其它绘图工具

Seaborn 建立在 matplotlib 之上,提供了更高级更方便的使用方式。
通过 Seaborn 可以很方面绘制出线各种常见关系的图形,比如聚类关系,线性关系,分布关系等:

In [120]: import numpy as np

In [121]: import matplotlib.pyplot as plt

In [122]: import seaborn as sns

In [123]: np.random.seed(sum(map(ord, "aesthetics")))

In [124]:

In [124]: def sinplot(flip=1):
     ...:     x = np.linspace(0, 14, 100)
     ...:     for i in range(1, 7):
     ...:         plt.plot(x, np.sin(x + i * .5) * (7 - i) * flip)
     ...:

In [125]: sns.set()

In [126]: sinplot()
In [127]: plt.show()

如下图:


Figure_10.png

Bokeh 是一个现代化的绘图工具,底层使用 D3.js 进行绘图,也就是说 Bokeh 绘制的图形是基于浏览器显示的,这也非常符合当今的技术潮流,而且绘制的图形交互功能更加强大。

In [131]: import numpy as np

In [132]: from bokeh.layouts import gridplot

In [133]: from bokeh.plotting import figure, show, output_file

In [134]: # sin曲线

In [135]: x = np.linspace(0, 4*np.pi, 100)

In [136]: y = np.sin(x)

In [137]: p = figure(title="Shiyanlou Bokeh Example")

In [138]: p.circle(x,  y, legend="sin(x)")
Out[138]: GlyphRenderer(id='9c2202a5-15c2-4282-b074-d3a964790ba7', ...)

In [139]: p.circle(x, 2*y, legend="2*sin(x)", color="orange")
Out[139]: GlyphRenderer(id='d3e000b9-c792-4321-a1a5-b51db3981841', ...)

In [140]: p.circle(x, 3*y, legend="3*sin(x)", color="green")
Out[140]: GlyphRenderer(id='ba52e19d-3238-463d-bfda-7dc9063fc070', ...)

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

推荐阅读更多精彩内容

  • 一、概述 深度学习的一个重要手段是训练数据和训练过程的可视化,因此,我们关于深度学习的系列介绍文章就从Matplo...
    aoqingy阅读 6,089评论 0 24
  • 申请季终于到了,准留学生们又开始了看最新一期排名选学校的季节。大家不要只顾着看那一字排开的学校名称,你们真的了解这...
    毛利大五郎_阅读 897评论 0 0
  • 春回大地枝吐芽 生机盎然万物长 重拾信心又出发 离家游子走天涯
    爱主爱人阅读 221评论 0 0
  • 恰恰好的挫折,不会将一个人打击到失去斗志,也不会让他觉得无关痛痒,能让其不断去增强自体的能力,提升自己的内聚力。任...
    423429d90f38阅读 162评论 0 0
  • 开心和悲伤一样好玩,勇敢和恐惧都很刺激,经历了无奈无助才更能增加内心力量。我们到这世界是来玩的!生命自身对完整的渴...
    shuangqq阅读 390评论 0 0