25. matplotlib

2023/08/21閱讀時間約 41 分鐘
raw-image

Hi, 大家好。我是茶桁。

在上一节课中,我们结束了Python正式的所有内容,但是咱们的Python课程还未结束。从这节课开始,我们要来学习一下Python的第三方库。

Python的生态非常完善也非常活跃,我们不太可能讲目前所有的第三方库全部都介绍一遍,只介绍几个有影响力并且和处理数据相关的。那今天第一Part,我们就先来学习matplotlib

在之后的课程中,Python的基础理论我就不会细讲了,咱们重点是要快速的认识和学会第三方库。有什么语法上的问题,可以翻看前面几节的教程。

matplotlib是什么?

raw-image

Matplotlib是一个Python 2D绘图库,它可以在各种平台上以各种硬拷贝格式和交互式环境生成出具有 出版品质的图形。 Matplotlib可用于Python脚本,Python和IPython shell,Jupyter笔记本,Web应用 程序服务器和四个图形用户界面工具包。

Matplotlib试图让简单的事情变得更简单,让无法实现的事情变得可能实现。 只需几行代码即可生成绘图,直方图,功率谱,条形图,错误图,散点图等。

为了简单绘图,pyplot模块提供了类似于MATLAB的界面,特别是与IPython结合使用时。 对于高级用户,您可以通过面向对象的界面或MATLAB用户熟悉的一组函数完全控制线条样式,字体属性,轴属性等。

那么,我们为什么要学习matplotlib呢?

可视化是在整个数据挖掘的关键辅助工具,可以清晰的理解数据,从而调整我们的分析方法。

能将数据进行可视化,更直观的呈现 使数据更加客观、更具说服力

例如下面两个图为数字展示和图形展示:

raw-image

以上两个图形中,第一组是完全的数据。我们基本很难看出这组数据到底谁大谁小,当然,从位数上我们还是可以比较容易辨认,但是比起第二张图呢?是不是第二张图就非常清晰的展示了数据的大小,一目了然?

那既然我们要学习的是数据可视化,我们首先要做的,必定是要先了解一下常见数据图表,知道其种类和意义。

常见图形种类及意义

我们首先要先了解具体的图形,才能知道我们在什么情况下使用什么图形来表示。

  • 折线图:以折线的上升或下降来表示统计数量的增减变化的统计图。特点是:能够显示数据的变化趋势,反映事物的变化情况。(变化)
raw-image
  • 散点图:用两组数据构成多个坐标点,考察坐标点的分布,判断两变量之间是否存在某种关联或总结坐标点的分布模式。特点是:判断变量之间是否存在数量关联趋势,展示离群点(分布规律)
raw-image
  • 柱状图:排列在工作表的列或行中的数据可以绘制到柱状图中。特点是:绘制连离散的数据,能够一眼看出各个数据的大小,比较数据之间的差别。(统计/对比)
raw-image
  • 直方图:由一系列高度不等的纵向条纹或线段表示数据分布的情况。 一般用横轴表示数据范围, 纵轴表示分布情况。特点是:绘制连续性的数据展示一组或者多组数据的分布状况(统计)
raw-image


  • 饼图:用于表示不同分类的占比情况,通过弧度大小来对比各种分类。特点是:分类数据的占比情况(占比)。
raw-image


matplotlib画图实现

首先我们要知道,Python的第三方库几乎全部都需要额外安装才行。我们之前在讲Python环境的时候有提到如何创建虚拟环境以及如何安装第三方库。那我们现在,就来直接安装一下,还记得么?我用的环境是conda, 所以我的安装命令都是使用conda的,不过你将其咱们课程中还是要使用最普遍的方式,所以以下我都会替换成pip

pip install motplotlib

执行完毕后,motplotlib就安装到您的Python环境内了。

建议在Python环境内安装好Jupyter来进行学习,你会发现简直太方便了。如果是在Jupyter内,那么会在代码执行之后的下方直接显示出结果,而如果我们是使用python xx.py来执行,那Python会调用内部的绘图器来进行显示。

Jupyter for vscode

raw-image

Python绘图器

raw-image


当然,你也可以自己在命令行内起一个Jupyter notebook服务,那就可以直接在浏览器上进行操作了。

Jupyter Notebook

raw-image


当然几种方法中,我还是最推崇在VSCode中进行。毕竟我们还是需要代码提示的。

在正式开始之前,让我们对matplotlib的图像结构建立一个认识:


raw-image

现在让我们来具体的实现一下,做一个简单的图形:

# 导入模块
import matplotlib.pyplot as plt
# 这段代码会让之后的代码在Jupyter内执行的时候显示图片
%matplotlib inline
# 传入x,y, 通过plot画图
plt.plot([1,0,9],[4,5,6])
# 在执行程序的时候显示图形
plt.show()

在这段代码中,我们使用plot来进行了绘制,xy分别是plot的两个参数,代表了x轴和y轴。那么这两个轴分别接受了一个列表,那就是有三个点,第一个点是(1,4), 第二个点是(0,5), 第三个点是(9,6)。最后,我们使用show()函数来进行最终呈现。


raw-image

绘图折线图

首先,我们来绘制一个折线图,这次我们用变量存储数据的方式:

# 绘制折线图
import matplotlib.pyplot as plt
x = range(1, 8) # x轴的位置
y = [17, 17, 18, 15, 11, 11, 13]
# 传入x,y,plot绘图
plt.plot(x, y)
plt.show()


raw-image

然后,我们对这个折线图进行一下设置,修改颜色和形状:

# 绘制折线图
import matplotlib.pyplot as plt
x = range(1, 8) # x轴的位置
y = [17, 17, 18, 15, 11, 11, 13]
# 传入x,y,plot绘图
plt.plot(x, y, color='red', alpha=0.5, linestyle='--', linewidth=3)
plt.show()


raw-image

我们对plot函数传递了几个参数修改了折线的样式,其中color是折线的颜色,alpha是折线的透明度(0-1), linestyle是折线的样式, linewidth是折线的宽度。

linestyle的几个值分别是:-实线(solid),这个也是默认值;--短线(dashed); -.短点相间线(dashdot); :虚线点(dotted)。

关键点样式

让我们接着进行修改这段折线样式:

...
# 传入x,y,plot绘图
plt.plot(x, y, color='red', alpha=0.5, linestyle='--', linewidth=3, marker='o')
plt.show()


raw-image

我们这次只增加了一个参数,很明显,marker就是关键点的样式。

折线和关键点到底有哪些值呢?我们看一下下面这个表:

raw-image


如果看不懂描述的小伙伴,最直接的办法就是放到代码里直接运行一下看看。

当然,我们还可以改变关键点的大小等参数:

plt.plot(x, y, color='red', alpha=0.5, linestyle='--', linewidth=3, marker='o', markersize='10',markeredgecolor='blue', markeredgewidth=3)

那这里面,markersize是表示关键点的大小,markeredgecolor是关键点边框的颜色,markeredgewidth就是关键点边框的宽度。


raw-image

既然图片渲染出来了,那我们总是需要进行保存的。那么下面,我们就看看如何将图片保存下来,在保存之前,我们还会根据需要设置一下图片的大小。

设置图片大小和保存

from matplotlib import pyplot as plt
import random
x = range(2, 26, 2) # x轴的位置
y = [random.randint(15, 30) for i in x]

# 设置图片大小
plt.figure(figsize=(20, 8), dpi=80)
plt.plot(x,y)
# plt.show()
# 保存
plt.savefig('./data/img/t1.png')

我们依次来看这段代码,里面有我们认识的也有我们不认识的。其中的random是为了生成随机数,这个我们就先不管了。直接看设置部分。

figsize这参数是为了指定figure的宽和高,单位为英寸。

dpi参数指定绘图对象的分辨率,即每英寸多少个像素,缺省值为80,1英寸等于2.5cm, A4纸为21*30cm的纸张。

然后我们继续往下看,savefig就是指定目录进行保存。这里我们需要注意两点:

  1. 如果保存的目录有路径不存在,则会报错无法保存。
  2. 我们需要savefig的时候尽量不要使用show方法,因为savefig也具备了展示图片的功能,并且,如果show存在的话,在展示完图片之后,会释放figuer资源,那么savefig保存下来的图片将会是空白的。就好比我们open('file', 'a+') as fp一个文件,在使用fp.write的时候没有往里面写入内容。因为这些内容被上面一个方法清空了,但是文件我还是会保存的,只是文件内没有任何内容。

然后我们回过头来继续看我们写的这段代码,其实savefig能存储的文件格式很多,包括能够存储svg格式的矢量图。只需要plt.savefig('./t1.svg'),保存的时候换一下后缀名就可以了。

现在让我们看下保存好的图片:


raw-image

绘制轴上的刻度

有没有发现,虽然我们折线图是正常的,但是似乎x轴上的刻度区间太大了,并不是所有关键点都明显展示出来了。那现在我们就来设置一下x轴和y轴的刻度。

...
# 设置x轴的刻度
plt.xticks(x)
# # 设置y轴的刻度
plt.yticks(y)

# 设置图片大小
plt.plot(x,y)
plt.show()

这段代码中我们将保存文件的代码去掉了。因为主要是进行设置,所以我们展示一下看看正确与否就行了。

raw-image


我们看到现在的图片,刻度上x轴遵循了我们之前对x的设定,(2, 26, 2), 从2开始,到25, 并且步进值为2.y轴呢?因为是随机数,所以关键点的分布并不均匀。

这个时候,我就又需要进行修改了,一个是y轴的刻度要分配的更均匀,再有就是x轴上,我希望区间为1,而不是2。让我们来对其进行下修改:

...
# 设置x轴的刻度
plt.xticks(range(1, 25))
# 设置y轴的刻度
plt.yticks(range(min(y), max(y)+1))

# 设置图片大小
plt.plot(x,y)
plt.show()
raw-image

似乎图不太一样,原因是因为我在代码中使用的是随机数函数random.randint来差生y轴的数据,所以每次生成的图片都会有些不同。

我们来好好看看轴线上的刻度。确实和关键点都对应上了。并且比起关键点来说更密集一点。原因就在于,我们将x的刻度点范围改为(1, 25),无步进值。y轴在绘制的时候也做了定义,范围设置为(最小的y值, 最大的y值+1),同样,也是没有步进值。这样,两个轴上的刻度分布就非常均匀了。

这里的关键知识点就是:我们可以使用xticksyticks来生成x轴刻度或者y轴刻度,并且,在其中可以传递参数来对x轴上的刻度和y轴上的刻度进行定义。

不过我们现在这个还是无法满足需求,原因就在于我们这个折线图是为了显示不同时间点上的温度变化。那么我们就必须要让x轴显示时间,而y轴显示温度。

让我们继续修改一下,这里我们就只展示轴线代码的修改:

# 构造x轴刻度标签
x_ticks_label = ["{}:00".format(i) for i in x]
# 让字旋转45
plt.xticks(x, x_ticks_label, rotation=45)

# 构造y轴的刻度标签
y_ticks_label = ["{}℃".format(i) for i in range(min(y), max(y)+1)]
plt.yticks(range(min(y), max(y)+1), y_ticks_label)

最后生成的图片:

raw-image

这里,我们使用了x_ticks_label来设置了x轴的刻度上显示的信息。当然,y轴也是相同的方式。然后将label传入轴刻度生成方法xticks中进行刻度生成,在生成的时候,我们还使用了xticks的参数rotation设置为45来完成了label的旋转。

设置显示中文

不过这并未结束,matplotlib默认是只显示英文的,无法显示中文。但是我们无论是刻度,图标题,很多时候都必须显示中文。该怎么办呢?

接下来就让我们来看看如何修改matplotlib的默认字体。这一段,我们重新写一个需求,来看看2个小时内每分钟跳动变化。

from matplotlib import pyplot as plt
from matplotlib import font_manager
import random

x = range(0, 120)
y = [random.randint(10, 30) for i in range(120)]

plt.figure(figsize=(20, 8), dpi=80)
plt.plot(x,y)


# 设置字体和Label
my_font = font_manager.FontProperties(fname='/System/Library/Fonts/PingFang.ttc', size=18)
plt.xlabel('时间', fontproperties=my_font)
plt.ylabel('次数', fontproperties=my_font)

# 设置标题
plt.title('每分钟跳动次数', fontproperties=my_font, color='red')

plt.show()


raw-image

我们引入了font_manager,然后利用它设置了我们需要用到的字体(必须是中文字体)给到一个变量my_font内。最后在设置label的时候,将字体设置为这个变量。

这样,我们就完成了中文字体的显示。

作为对比,我们来看看这样设置的是什么样:

...
plt.xlabel('时间')
plt.ylabel('次数')
plt.title('每分钟跳动次数',color='red')

plt.show()


raw-image

一图多线

大多数时候,我们的一张图表上可能不仅需要一条线。而是两条线相互交错。这就形成了两组数据的对比,我们打个比方来说:我们正在和一位同事竞争销售额,需要查看去年(2022年)全年的数据对比:

# 销售额数据对比
y1 = [20,10,10,20,40,30,40,40,50,60,50,40]
y2 = [10,30,20,30,40,20,10,30,30,80,30,20]
x = range(1, 13)

# 设置图形
plt.figure(figsize=(20, 8), dpi=80)

plt.plot(x, y1, color='orange', label="茶桁")
plt.plot(x, y2, color='green', label='同事')

# 设置x轴刻度
xtick_labels = ['{}月'.format(i) for i in x]
my_font = font_manager.FontProperties(fname='/System/Library/Fonts/PingFang.ttc', size=24)

plt.xticks(x, xtick_labels, fontproperties=my_font, rotation=45)

# 绘制网格
plt.grid(alpha=0.4) #网格也可以设置样式,这里透明度为0.4

# 添加图例(注意:只有在这里需要添加prop参数是显示中文,其他的都用fontproperties)
# 设置位置loc : upper left、 lower left、 center left、 upper center
plt.legend(prop=my_font, loc='upper right')

plt.show()

我们在代码中设置两两组数据,分别为y1, y2。这两组数据一共12个,对应了12个月份。然后我们在plot方法中设置了线条的颜色,设置了这条线条对应的数据,并且添加了label。意在对这个线条写个说明。

在之后,我们添加了grid网格,意图让线条上的关键点更明显。

最后使用legend来完成plot中设置的label的显示,并在其中设置了显示所用字体。这里需要注意的是,在legend方法中设置字体所用的形参是prop而非fontproperties。在最后,我们使用loc设置了这两个label显示的位置,其中的关键字upper right代表的是两个方位「上,右」,来确定显示位置为右上角。

最后,我们绘制的图片显示如图:

raw-image


从图上能明显看出来,我的销售数据是在稳步上升的,而同事起伏比较大。大部分时候我占优势,可是旺季时顶峰数据同事比我高很多,所以说基本上是各有千秋。

基于折线图,我们再来看几个拓展的部分。

首先,我们在绘图的时候,实际上是支持多个坐标系绘制在一张图上的。这也经常是数据图对比经常用到的方式:

# 多个坐标系子图 add_subplot方法,给figure新增子图
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(1, 100)
fig = plt.figure(figsize=(20, 10), dpi=80)

# 子图1
ax1 = fig.add_subplot(2,2,1)
ax1.plot(x,x)
# 子图2
ax2 = fig.add_subplot(2,2,2)
ax2.plot(x, x**2)
ax2.grid(color='r', linestyle='--', linewidth=1, alpha=0.3)
# 子图3
ax3 = fig.add_subplot(2,2,3)
ax3.plot(x, np.log(x))

plt.show()

我们利用add_subplot方法,在一个figure上添加了三个子图。

其次,有一些时候,我们需要对坐标轴范围进行设定

# 设定坐标轴范围
x = np.arange(-10, 11, 1)
y = x ** 2
plt.plot(x,y)

# plt.xlim([-5,5])

# 单边调整
# plt.xlim(xmin=-4)
# plt.xlim(xmax=4)

plt.ylim(ymin=0)
plt.xlim(xmin=0)

plt.show()

在这段代码中,我展示了三个调整范围的方式。

第一个是使用数组划定范围来进行调整。

第二个方式是分别设定一边的值(最小值或者最大值)。

最后一个方式是只设定x轴和y轴的最小值。下图展示的是第三个方式绘制的图:

raw-image


当然,坐标轴并不会是一成不变的。有的时候我们可能需要y轴在x轴的正中间。所以我们需要改变坐标轴的默认显示方式

我们先来看看原本的图默认样式是什么样:

# 改变坐标轴的默认显示方式
y = range(0, 14, 2)
x = [-3, -2, -1, 0, 1, 2, 3]
plt.figure(figsize=(20,8), dpi=80)

plt.plot(x,y)
plt.show()


raw-image

然后我们对这张图进行修改,获取图像之后设置四周边线,并且移动底边,移动到y轴的0位置

# 改变坐标轴的默认显示方式
y = range(0, 14, 2)
x = [-3, -2, -1, 0, 1, 2, 3]
plt.figure(figsize=(20,8), dpi=80)

# 获得当前图表的图像
ax = plt.gca()

# 设置图形四周的边线
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_color('blue')
ax.spines['left'].set_color('red')

# 设置底边的移动范围,移动到y轴的0位置,`data`: 移动轴的位置到交叉轴的指定坐标
ax.spines['bottom'].set_position(('data', 0))
ax.spines['left'].set_position(('data', 0))

plt.plot(x,y)
plt.show()

代码中,我们使用gca()获取了图像赋值给变量ax,然后对其进行修改,spines可以修改四周边线,包括颜色和位置等。分别设置完颜色之后,我们分别对底边和左边使用了set_position进行了位移。移动到0点位置。那其实,底边对应的就是x轴,左边对应的就是y轴。

raw-image


绘制散点图

我们拿到了一组数据,就是今年3月份每天的最高气温,现在我想在图表上进行展示。为了展示气温的分布,我们准备使用散点图进行展示。

# 绘制散点图
y = [11,17,16,11,12,11,12,6,6,7,8,9,12,15,14,17,18,21,16,17,20,14,15,15,15,19,21,22, 22,22,23]
x = range(1,32)

plt.figure(figsize=(20,8),dpi=80)
# 使用scatter绘制散点图
plt.scatter(x, y, label='3月份')
plt.show()


raw-image

本来这样就已经完成绘制了。不过我们看一下图表,虽然散点是绘制完成了,但是整张图上我们看不出太多信息,包括刻度值,月份等等,另外,我记得咱们之前加过图例,现在我们都加上:

from matplotlib import font_manager
# 绘制散点图
y = [11,17,16,11,12,11,12,6,6,7,8,9,12,15,14,17,18,21,16,17,20,14,15,15,15,19,21,22, 22,22,23]
x = range(1,32)

plt.figure(figsize=(20,8),dpi=80)
# 使用scatter绘制散点图
plt.scatter(x, y, label='3月份')

my_font = font_manager.FontProperties(fname='/System/Library/Fonts/PingFang.ttc', size=12)
_xticks_labels = ['3月{}日'.format(i) for i in x]

plt.xticks(x[::3], _xticks_labels[::3], fontproperties=my_font, rotation=45)
plt.xlabel('日期', fontproperties=my_font)
plt.ylabel('温度', fontproperties=my_font)

# 图例
plt.legend(prop=my_font)

plt.show()

以上代码中的内容,基本都是咱们之前学过的内容,我就不多做解释了。其中,我们可以看到,plt.之后的方法就是绘制不同的图形,之前我们看到的plot是折线图,这次我们学到scatter是散点图。在图形绘制之后,剩下的就是对其进行修饰和设置。


raw-image

绘制条形图

今天刷到一条新闻,说目前2023年暑期档电影的票房基本已经定型,目前全部累计票房已经超过2019年称为历史最高暑期档,而最引人瞩目的是,国产电影全线压制好莱坞大片。这真是一个值的骄傲的事情。那现在,我们就来展现一下暑期档电影票房的对比吧,我们一步一步来,最开始当然是拿到数据。

本数据来源于猫眼,2023年8月20日14:00的实时数据,后期未下线的电影数据可能会有变化。

a = ['消失的她','碟中谍7:致命清算','芭比','八角笼中','茶啊二中','热烈','长安三万里','巨齿鲨2:深渊','封神第一部','孤注一掷']
b = ['35.22','3.46','2.47','21.92','3.66','8.69','17.56','7.53','22.36','26.48']

然后我们就可以开始绘制柱状图了:

plt.figure(figsize=(20,8), dpi=80)
plt.bar(range(len(a)), [float(i) for i in b], width=0.3)
plt.show()


raw-image

现在图形是绘制出来了,但是完全无法让人满意。我们并不知道哪个柱子是哪个电影的,并且对比之下,我们只能看出大概高低,并不知道具体的票房。那我们现在来进行修改, 先加上x轴和y轴上的刻度标识,并且将y轴刻度范围放大。

plt.xticks(range(len(a)), a, fontproperties=my_font)
plt.yticks(range(0,51,5), range(0,51,5))


raw-image

目前的图我们是能看出谁是谁了,而且比起刚才看起来y轴上也舒服了很多,没有顶天立地。

接下来,我们继续修改。给柱子加上颜色,好做区分。并且将绘制的图形赋值给到变量rects,在下面我们好对每一根柱子上写一个数字,将票房数值写上去。这样,具体的票房我们就能一目了然。

a = ['消失的她','碟中谍7:致命清算','芭比','八角笼中','茶啊二中','热烈','长安三万里','巨齿鲨2:深渊','封神第一部','孤注一掷']
b = ['35.22','3.46','2.47','21.92','3.66','8.69','17.56','7.53','22.36','26.48']

plt.figure(figsize=(20,8), dpi=80)
rects = plt.bar(range(len(a)), [float(i) for i in b], width=0.3, color=['r','g','b','r','g','b','r','g','b','r'])
plt.xticks(range(len(a)), a, fontproperties=my_font)
plt.yticks(range(0,51,5), range(0,51,5))

# 加标注(水平居中)
for rect in rects:
height = rect.get_height()
plt.text(rect.get_x()+rect.get_width() / 2, height+1, str(height), ha='center')

plt.show()

这段代码中其他的都好理解,就是加标注这一段。我们使用forrects中分别获取到每一根柱子,然后设定了一个高,这个高度就是柱子的实际高度。再设定一个text给到这根柱子,text的高度为柱子的定位为每根柱子的x轴位置+其宽度的二分之一,高度为柱子高度+1, 字符串为柱子高度本身,设置水平居中。

来,让我们看看效果:

raw-image


现在,我们的显示虽然还是不完美,但是已经非常清晰了。

当然,柱状图除了竖向的,还有横向,但是横向就不能称之为柱状图,而是条形图:

# 横向条形图
a = ['消失的她','碟中谍7:致命清算','芭比','八角笼中','茶啊二中','热烈','长安三万里','巨齿鲨2:深渊','封神第一部','孤注一掷']
b = ['35.22','3.46','2.47','21.92','3.66','8.69','17.56','7.53','22.36','26.48']

plt.figure(figsize=(20,8), dpi=80)
rects = plt.barh(range(len(a)), [float(i) for i in b], height=0.5, color=['r','g','b','r','g','b','r','g','b','r'])
plt.xticks(range(0,51,5), range(0,51,5))
plt.yticks(range(len(a)), a, rotation=45, fontproperties=my_font)

# 加标注(水平居中)
for rect in rects:
width = rect.get_width()
plt.text(width+1, rect.get_y()+0.5/2, str(width)+' 亿', va='center', fontproperties=my_font)

plt.show()


raw-image

其方法和原理都和柱状图是一样的,不同的点就在于柱状图的方法是bar,横向条形图的方法为barh。另外,别忘了切换x,y轴。

在这里,恭喜《封神》破22亿,加油...

我们平时看到的柱状图或者条形图,一定不只是这样一根一根的,还有那种两根或两根以上并列的对吧?其形式也很简单,就是在当前的柱子旁边多加一根而已:

# 多条并列
index = np.arange(4)
BJ = [50,55,53,60]
SH = [44,66,55,41]
# 并列
plt.bar(index,BJ, width=0.3)
plt.bar(index+0.3, SH, width=0.3, color='green')

plt.xticks(index+0.3/2, index)
plt.show()


raw-image

直方图

这个图形的学习,我们还是拿电影数据来做,但是这次我们不拿刚才用过的数据了,我们拿到一个250部电影的时长数据,现在我们要统计处这些电影时长的分布状态。(比如,市场为100分钟到120分钟的电影数量,出现频率等),我们该如何去做呢?

来,让咱们尝试一下,还是老样子,先落位数据:

times = [131,98,125,131,124,139,131,117,128,108,135,138,131,102,107,114,119,128,121,142,127,130,124,101,110,116,117,110,128,128,115,99,95,138,117,111,78,132,124,113,150,110,117,136,126,134,95,144,105,126,130,126,130,126,116,123,106,112,138,123,99,136,123,117,119,105,137,123,128,125,104,109,134,125,127,105,120,107,129,116,108,132,103,136,118,102,120,114,105,115,132,145,119,121,112,139,125,138,109,132,134,156,106,117,127,144,139,139,119,140,83,110,102,123,107,143,115,136,118,139,123,112,118,125,109,119,133,112,114,122,109,106,123,116,131,127,115,118,112,135,115,146,137,116,103,144,83,123,111,110,111,100,154,136,100,118,119,133,134,106,129,126,110,111,109,141,120,117,106,149,122,122,110,118,127,121,114,125,126,114,140,103,130,141,117,106,114,121,114,133,137,92,121,112,146,97,137,105,98,117,112,81,97,139,113,134,106,144,110,137,137,111,104,117,100,111,101,110,105,129,137,112,120,113,133,112,83,94,146,133,101,131,116,111,84,137,115,122,106,144,109,123,116,111,111,133,150,134,76,104] 
print(len(times))

---
250

没问题,250个数据齐了。现在让我们来开始绘图:

plt.figure(figsize=(20,8), dpi=80)
# 设置组距
distance = 2
# 计算组距
group_num = int((max(times) - min(times)) / distance)
plt.hist(times, bins=group_num)

plt.xticks(range(min(times), max(times))[::2])
plt.grid(linestyle='--', alpha=0.5)
plt.xlabel('电影时长大小', fontproperties=my_font)
plt.ylabel('电影的数据量', fontproperties=my_font)
plt.show()

从代码中看,直方图的方法是hist, 其中参数为需要展示的数据和组距。

x轴刻度上,我们将最小的电影时长和最大的电影时长顺序分布,步进值为2。

raw-image


现在我们从图中能看到,110 ~ 112这个时间段的电影数量是最多的,其次就是116 ~ 118分钟的。

现在,我们更清晰的感受了i库55起1422

直方图的作用。

饼状图

最后我们来看看饼状图,饼状图相信大家平时看的也很多。基本上,我们遇到比例,份额对比的时候会使用这个图形。

来,让我们先绘制一个基本图形:

size = [55, 35, 10]  # 各部分大小

plt.figure(figsize=(20,8), dpi=100)
plt.pie(size)
plt.show()


raw-image

现在让我们在这个基础的饼状图上进行设置和修改,首先,我们需要这个图形各个区域都有个名称,然后是我们自己设定下他们的颜色,而不是用默认的,接着,我们需要将其中一部分突出显示。

# 修改生成饼图代码
plt.pie(size,
explode=[0, 0.05, 0],
colors = ['r','g','b'],
labels = ['第一部分','第二部分','第三部分'])


raw-image

现在是按照我刚才希望的去变化了,但是并不让人满意。我们需要将文字设置成中文显示,然后整个图形旋转一下,让突出的部分部要向下,接着我们希望显示出百分比,并且有一个图例,分别标识出颜色和区域的文字。

size = [55, 35, 10]  # 各部分大小

plt.figure(figsize=(20,8), dpi=100)

label_list = ['第一部分','第二部分','第三部分'] # 各部分标签
color = ['red', 'green', 'blue'] # 各部分颜色
explode = [0, 0.05, 0] # 各部分突出值
patches, l_text, p_text = plt.pie(size,
explode = explode,
colors = color,
labels = label_list,
labeldistance=1.1,
autopct='%1.1f%%',
shadow=False,
startangle=150,
pctdistance=0.6)

for t in l_text:
print(dir(t))
t.set_fontproperties(my_font)
for t in p_text:
t.set_size(18)
for i in patches:
i.set_color('pink')
break

plt.legend(prop=my_font)
plt.show()

我们在这段代码中,将之前在pie方法中的三组列表数据拿出来赋值给了三个变量,然后增加了一些其他参数用于标签距离、设置旋转、百分比距离等。

然后将生成的图赋值给到三个变量,patches, l_text, p_text,这三个变量分别接受的参数为「饼的区域」、「饼的外部说明文字」、「饼的内部标识文字」。

然后,对这三个变量分别进行设置。

最后,将图例的字体设置一下,然后显示出来。

raw-image


总结

今天的课程到这里也就结束了。最后让我们来总结一下

raw-image

最后,我们留个作业吧,好久没留作业了。将咱们之前做的这个饼图加上阴影,扩大分离的那块区域的分离距离。如图:

raw-image

小伙伴们,记得认真学习并且完成作业。

好,下课。

茶桁
茶桁
80后,先后在多家大厂担任数据产品经理,中台产品。
留言0
查看全部
發表第一個留言支持創作者!