当前位置:   article > 正文

Matplotlib数据可视化(二)_linewidth matplotlib

linewidth matplotlib

Task02
本次学习参照Datawhale开源学习:https://github.com/datawhalechina/fantastic-matplotlib
内容大体源自原文,结合自己学习思路有所调整。
个人总结:一、matplotlib有三个层次的API:FigureCanvas、Renderer、Artist。前两个处理程序和计算机的底层交互,第三项Artist就是具体的调用接口来作图。二、Artist有两种类型:primitives 和containers。primitive是内容要素,画具体的点线面。container是框架设计,用来装基本要素,比如画布figure、子图Axes和轴Axis等。

2. 艺术画笔

2.1. matplotlib的三层api

matplotlib的基本原理是用Artist类在画布(Canvas)上绘制(Render)图形。对应的,matplotlib有三个层次的API:
matplotlib.backend_bases.FigureCanvas 绘图区,所有的图像都是在绘图区完成
matplotlib.backend_bases.Renderer 渲染器,控制如何在 FigureCanvas 上画图。
matplotlib.artist.Artist 图表组件,即调用Render的接口在Canvas上作图。
前两者处理程序和计算机的底层交互,第三项Artist调用接口作图。因此从用户交互面角度,我们通常都是在使用matplotlib.artist.Artist类来进行画图。

2.2. Artist

Artist分为两个部分:primitives(基本要素)和containers(容器)。

primitive包含标准图形对象,如曲线Line2D,文字text,矩形Rectangle,图像image等。

container用来装基本要素,如图形figure、坐标系Axes和坐标轴Axis等。

matplotlib使用流程

matplotlib的标准流程为:

  1. 创建一个Figure实例
  2. 使用Figure实例创建一个或者多个AxesSubplot实例
  3. 使用Axes实例的辅助方法来创建primitive
import matplotlib.pyplot as plt
import numpy as np

# step 1 创建一个Figure实例
fig = plt.figure()

# step 2 用Figure实例创建subplot
ax = fig.add_subplot(2, 1, 1) 

# step 3 用Axes实例画一条曲线
t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2*np.pi*t)
line, = ax.plot(t, s, color='blue', lw=2)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在这里插入图片描述

2.3. primitives基本要素

容器中可能会包含多种primitives,它主要有几种类型:线-Lines,二维图-Patches,图像-image,文本-Text 等。

2.3.1. 线-Lines

主要介绍曲线-Line2D。matplotlib绘制曲线主要是通过matplotlib.lines 下的matplotlib.lines.Line2D 类来完成的。matplotlib中line的含义:它表示的可以是连接所有顶点的实线样式,也可以是每个顶点的标记。
它的构造函数:

class matplotlib.lines.Line2D(xdata, ydata, linewidth=None, linestyle=None, color=None, marker=None, markersize=None, markeredgewidth=None, markeredgecolor=None, markerfacecolor=None, markerfacecoloralt='none', fillstyle=None, antialiased=None, dash_capstyle=None, solid_capstyle=None, dash_joinstyle=None, solid_joinstyle=None, pickradius=5, drawstyle=None, markevery=None, **kwargs)
  • 1

常用的的参数有:

  • xdata:需要绘制的line中点的在x轴上的取值,若忽略,则默认为range(1,len(ydata)+1)
  • ydata:需要绘制的line中点的在y轴上的取值
  • linewidth:线条的宽度
  • linestyle:线型
  • color:线条的颜色
  • marker:点的标记
  • markersize:标记的size

如何绘制曲线-Line2D

  1. pyplot方法绘制
# 1. pyplot方法绘制
import matplotlib.pyplot as plt
x = range(0,5)
y = [2,5,7,8,10]
plt.plot(x,y)
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述

  1. Line2D对象绘制
# 2. Line2D对象绘制
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D      

fig = plt.figure()
ax = fig.add_subplot(111)
line = Line2D(x, y)
ax.add_line(line)
ax.set_xlim(min(x), max(x))
ax.set_ylim(min(y), max(y))

plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述
如何设置曲线-Line2D属性

  1. 直接在plot()函数中设置
# 1) 直接在plot()函数中设置
import matplotlib.pyplot as plt
x = range(0,5)
y = [2,5,7,8,10]
plt.plot(x,y, linewidth=10) # 设置线的粗细参数为10
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 对线对象进行设置
# 2) 通过获得线对象,对线对象进行设置
x = range(0,5)
y = [2,5,7,8,10]
line, = plt.plot(x, y, '-')
line.set_antialiased(False) # 关闭抗锯齿功能
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 使用setp()函数设置
# 3) 获得线属性,使用setp()函数设置
x = range(0,5)
y = [2,5,7,8,10]
lines = plt.plot(x, y)
plt.setp(lines, color='r', linewidth=10)
  • 1
  • 2
  • 3
  • 4
  • 5

2.3.2. 二维图-Patches

matplotlib.patches.Patch类是二维图形类。它的构造函数:

Patch(edgecolor=None, facecolor=None, color=None,
linewidth=None, linestyle=None, antialiased=None,
hatch=None, fill=True, capstyle=None, joinstyle=None,
**kwargs)

主要介绍Rectangle-矩形Rectangle矩形类在官网中的定义是: 通过锚点xy及其宽度和高度生成。Rectangle本身的主要比较简单,即xy控制锚点,width和height分别控制宽和高。它的构造函数:

class matplotlib.patches.Rectangle(xy, width, height, angle=0.0, **kwargs)

在实际中最常见的矩形图是**hist直方图bar条形图**。
1) hist-直方图

matplotlib.pyplot.hist(x,bins=None,range=None, density=None, bottom=None, histtype=‘bar’, align=‘mid’, log=False, color=None, label=None, stacked=False, normed=None)

下面是一些常用的参数:

  • x: 数据集,最终的直方图将对数据集进行统计
  • bins: 统计的区间分布
  • range: tuple, 显示的区间,range在没有给出bins时生效
  • density: bool,默认为false,显示的是频数统计结果,为True则显示频率统计结果,这里需要注意,频率统计结果=区间数目/(总数*区间宽度),和normed效果一致,官方推荐使用density
  • histtype: 可选{‘bar’, ‘barstacked’, ‘step’, ‘stepfilled’}之一,默认为bar,推荐使用默认配置,step使用的是梯状,stepfilled则会对梯状内部进行填充,效果与bar类似
  • align: 可选{‘left’, ‘mid’, ‘right’}之一,默认为’mid’,控制柱状图的水平分布,left或者right,会有部分空白区域,推荐使用默认
  • log: bool,默认False,即y坐标轴是否选择指数刻度
  • stacked: bool,默认为False,是否为堆积状图

绘制直方图的方法和绘制直线方法也一样分为使用pyplot绘制和使用Rectangle类绘制。

2) bar-柱状图

matplotlib.pyplot.bar(left, height, alpha=1, width=0.8, color=, edgecolor=, label=, lw=3)

下面是一些常用的参数:

  • left:x轴的位置序列,一般采用range函数产生一个序列,但是有时候可以是字符串
  • height:y轴的数值序列,也就是柱形图的高度,一般就是我们需要展示的数据;
  • alpha:透明度,值越小越透明
  • width:为柱形图的宽度,一般这是为0.8即可;
  • color或facecolor:柱形图填充的颜色;
  • edgecolor:图形边缘颜色
  • label:解释每个图像代表的含义,这个参数是为legend()函数做铺垫的,表示该次bar的标签

绘制柱状图的方法和直方图一样分为使用pyplot绘制和使用Rectangle类绘制。

2.3.3. 图像-image

images是matplotlib中绘制image图像的类,其中最常用的imshow可以根据数组绘制成图像,它的构造函数:

class matplotlib.image.AxesImage(ax, cmap=None, norm=None, interpolation=None, origin=None, extent=None, filternorm=True, filterrad=4.0, resample=False, **kwargs)

imshow根据数组绘制图像

matplotlib.pyplot.imshow(X, cmap=None, norm=None, aspect=None, interpolation=None, alpha=None, vmin=None, vmax=None, origin=None, extent=None, shape=, filternorm=1, filterrad=4.0, imlim=, resample=None, url=None, *, data=None, **kwargs)

使用imshow画图时首先需要传入一个数组,数组对应的是空间内的像素位置和像素点的值,interpolation参数可以设置不同的差值方法。

import matplotlib.pyplot as plt
import numpy as np
methods = [None, 'none', 'nearest', 'bilinear', 'bicubic', 'spline16',
           'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', 'quadric',
           'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos']


grid = np.random.rand(4, 4)

fig, axs = plt.subplots(nrows=3, ncols=6, figsize=(9, 6),
                        subplot_kw={'xticks': [], 'yticks': []})

for ax, interp_method in zip(axs.flat, methods):
    ax.imshow(grid, interpolation=interp_method, cmap='viridis')
    ax.set_title(str(interp_method))

plt.tight_layout()
plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

在这里插入图片描述

2.4. container容器

容器会包含一些primitives,并且容器还有它自身的属性。 比如Axes Artist,它是一种容器,它包含了很多primitives,比如Line2DText;同时,它也有自身的属性,比如xscal,用来控制X轴是linear还是log的。

2.4.1. Figure容器

matplotlib.figure.FigureArtist最顶层的container-对象容器,它包含了图表中的所有元素。一张图表的背景就是在Figure.patch的一个矩形Rectangle。 当我们向图表添加Figure.add_subplot()或者Figure.add_axes()元素时,这些都会被添加到Figure.axes列表中。

Figure也有它自己的text、line、patch、image。你可以直接通过add primitive语句直接添加。但是注意Figure默认的坐标系是以像素为单位,你可能需要转换成figure坐标系:(0,0)表示左下点,(1,1)表示右上点。

Figure容器的常见属性:
Figure.patch属性:Figure的背景矩形
Figure.axes属性:一个Axes实例的列表(包括Subplot)
Figure.images属性:一个FigureImages patch列表
Figure.lines属性:一个Line2D实例的列表(很少使用)
Figure.legends属性:一个Figure Legend实例列表(不同于Axes.legends)
Figure.texts属性:一个Figure Text实例列表

2.4.2. Axes容器

matplotlib.axes.Axes是matplotlib的核心。大量的用于绘图的Artist存放在它内部,并且它有许多辅助方法来创建和添加Artist给它自己,而且它也有许多赋值方法来访问和修改这些Artist

Figure容器类似,Axes包含了一个patch属性,对于笛卡尔坐标系而言,它是一个Rectangle;对于极坐标而言,它是一个Circle。这个patch属性决定了绘图区域的形状、背景和边框。

Axes有许多方法用于绘图,如.plot()、.text()、.hist()、.imshow()等方法用于创建大多数常见的primitive(如Line2D,Rectangle,Text,Image等等)。在primitives中已经涉及,不再赘述。

Subplot就是一个特殊的Axes,其实例是位于网格中某个区域的Subplot实例。其实你也可以在任意区域创建Axes,通过Figure.add_axes([left,bottom,width,height])来创建一个任意区域的Axes,其中left,bottom,width,height都是[0—1]之间的浮点数,他们代表了相对于Figure的坐标。

Axes还包含两个最重要的Artist container:
ax.xaxis:XAxis对象的实例,用于处理x轴tick以及label的绘制
ax.yaxis:YAxis对象的实例,用于处理y轴tick以及label的绘制

2.4.3. Axis容器

matplotlib.axis.Axis实例处理tick linegrid linetick label以及axis label的绘制,它包括坐标轴上的刻度线、刻度label、坐标网格、坐标轴标题。通常你可以独立的配置y轴的左边刻度以及右边的刻度,也可以独立地配置x轴的上边刻度以及下边的刻度。刻度包括主刻度和次刻度,它们都是Tick刻度对象。

Axis也存储了用于自适应,平移以及缩放的data_intervalview_interval。它还有Locator实例和Formatter实例用于控制刻度线的位置以及刻度label。

每个Axis都有一个label属性,也有主刻度列表和次刻度列表。这些ticksaxis.XTickaxis.YTick实例,它们包含着line primitive以及text primitive用来渲染刻度线以及刻度文本。

2.4.4. Tick容器

matplotlib.axis.Tick是从FigureAxesAxisTick中最末端的容器对象。Tick包含了tickgrid line实例以及对应的label

所有的这些都可以通过Tick的属性获取,常见的tick属性有
Tick.tick1line:Line2D实例
Tick.tick2line:Line2D实例
Tick.gridline:Line2D实例
Tick.label1:Text实例
Tick.label2:Text实例

y轴分为左右两个,因此tick1对应左侧的轴;tick2对应右侧的轴。
x轴分为上下两个,因此tick1对应下侧的轴;tick2对应上侧的轴。

思考

  1. primitives 和 container的区别和联系是什么?
    primitive是内容要素,画具体的点线面。container是框架设计,用来装基本要素,比如画布figure、子图Axes和轴Axis等。
  2. 四个容器的联系和区别是么?他们分别控制一张图表的哪些要素?
    Figure,Axes,Axis,Tick四个容器是包含关系。Figure是最底层画布,Axes是画布上的子图,Axis是子图的刻度网格,Tick是最末端的label等。

绘图

  1. 使用提供的drug数据集,画出折线图。
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

Dataset = pd.read_csv('../data/Drugs.csv')
group = Dataset.groupby(['YYYY','State']).agg('sum').reset_index()
df = group.pivot(index='YYYY', columns='State', values='DrugReports').reset_index()

# 创建figure和axes
fig, ax = plt.subplots(figsize=(10, 10))

# 设置网格颜色
ax.grid(True, color='white')

# 设置子图填充
rect = ax.patch
rect.set_facecolor('#eaeaf2')

# 设置边界透明
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)

# 绘制折线图
ax.plot(df['YYYY'], df['KY'], label='KY', color='#d8d8df')  
ax.plot(df['YYYY'], df['OH'], label='OH', color='#d8d8df')  
ax.plot(df['YYYY'], df['PA'], label='PA', color='orange', lw=3)  
ax.plot(df['YYYY'], df['VA'], label='VA', color='#d8d8df')  
ax.plot(df['YYYY'], df['WV'], label='WV', color='#d8d8df')  

# 设置标签
ax.set_xlabel('Year')
ax.set_ylabel('DrugReports')

# 设置刻度
ax.tick_params(tick1On=False)

# 设置标题
ax.set_title('Evolution of PA vs other states', color='orange', loc='left')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

在这里插入图片描述

  1. 分别用一组长方形柱和填充面积的方式模仿画出下图,函数 y = -1 * (x - 2) * (x - 8) +10 在区间[2,9]的积分面积。
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
import numpy as np

# 曲线数据
x = np.linspace(0, 10)
y = -1 * (x - 2) * (x - 8) + 10

# 显式创建figure和axes
fig, ax = plt.subplots(2,1, figsize = (6, 8))

# 绘制曲线
ax[0].plot(x, y, color='red')
ax[1].plot(x, y, color='red')

# 设置ylim从0开始
ax[0].set_ylim(0)
ax[1].set_ylim(0)

# 绘制柱状图
x_bar = np.linspace(2, 9)
y_bar = -1 * (x_bar - 2) * (x_bar - 8) + 10
ax[0].bar(x_bar, y_bar, width=0.1, color='lightgray')
ax[1].bar(x_bar, y_bar, width=0.15, color='lightgray')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/166882
推荐阅读
  

闽ICP备14008679号