书名:从0到1——Python数据可视化
ISBN:978-7-115-58713-8
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
著 莫振杰
责任编辑 赵 轩
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
读者服务热线:(010)81055410
反盗版热线:(010)81055315
读者服务:
微信扫码关注【异步社区】微信公众号,回复“e58713”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。
作者根据自己多年的前后端开发经验,站在完全零基础读者的角度,详尽介绍了Python数据可视化的基础知识,以及大量的开发技巧。本书分为3篇,围绕Python的3个主要数据可视化库进行详细的讲解:Python中最基础的可视化库Matplotlib、在实际工作中首选的Seaborn、可以在网站后台中实现数据可视化的Pyecharts。读者将这3个数据可视化库掌握,就能够解决90%以上的开发需求。最后还有附录帮助读者快速查找3个数据可视化库中常用的绘图函数。
本书适合完全0基础的初学者、想要系统学习的Python工程师、大中院校相关专业的老师和学生使用。
一本好的书就如指路明灯,不仅可以让小伙伴们学得更轻松,更重要的是可以让初学者少走很多弯路。如果你需要的并不是“大而全”,而是恰到好处的教程,那么不妨看看从0到1这个系列的书。
就像经典的冰山理论——第一眼看到的美,只是全部创造的八分之一。实际上,这个系列的书源自我多年开发工作的经验总结,除了技术介绍外,也融入了自己非常多的思考。虽是一名技术工程师,但实际上也是一个对文字非常敏感的人。对于技术书的写作来说,我更喜欢用简单的语言把“丰满”的知识呈现出来。
在接触任何一门技术时,我都会记录初学时遇到的各种问题,以及自己的各种思考。所以我比较了解初学者的心态,也知道怎样才能让小伙伴们快速而无阻碍地学习。对于从0到1系列图书来说,我更多的是站在初学者的角度,而不是已学会者的角度来编写的。
从0到1系列图书从基本语法出发,并延伸到了Python的各个重要领域,包括网络爬虫、数据分析、数据可视化等。这个系列的几本书连贯性非常强,这样做也是为了让小伙伴们能够一步到位地系统学习,而不至于浪费大量时间走弯路。
最后想要跟小伙伴们说的是:或许从0到1系列图书并不完美,但相信其独树一帜的讲解方式能够让小伙伴们的学习步伐走得更快、走得更远。
● 零基础的初学者。
● 想要系统学习Python的工程师。
● 高校相关专业的老师和学生。
绿叶学习网是我开发的一个开源技术网站,也是从0到1系列图书的配套资源网站。本书的所有配套资源都可以在该网站下载。
此外,小伙伴们如果有任何技术方面的问题,或想要获取更多学习资源,以及希望和更多技术“大牛”进行交流,可以加入我们的官方QQ群:280972684、387641216。
书中所有数据均为便于读者理解的虚拟数据,不具备其他任何用途,仅供编程练习。并且数据的数值、单位皆为举例,不具备实际功能与价值。
在编写本书的过程中,我得到了很多人的帮助。首先要感谢赵轩老师(本书责任编辑),感谢他这么多年的照顾,他是一位非常专业而不拘一格的编辑。
感谢五叶草团队的一路陪伴,感谢韦雪芳、陈志东、秦佳、莫振浩这几位小伙伴花费大量时间对本书进行细致的审阅,并且给出了诸多非常好的建议。
最后要特别感谢我的妹妹莫秋兰,她一直都在默默地支持和关心我。有这样一个善解人意的妹妹,是我一生中非常幸运的事情。
由于个人水平有限,书中难免存在疏漏之处,小伙伴们如果发现问题或有任何意见,可以登录绿叶学习网或发邮件(lvyestudy@qq.com)与我联系。
莫振杰
莫振杰
全栈工程师、产品设计师,涉猎前端、后端、Python等多个领域,熟练掌握JavaScript、Vue、React、Node.js、Python等多门技术。拥有一个高人气的个人网站——绿叶学习网,用于分享开发经验以及各种技术。
他还是多本图书的作者,凭着“从0到1”系列图书,获得了“人民邮电出版社IT图书2020年最有影响力作者”称号。
本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。
本书提供如下资源:
● 本书源代码;
● 书中彩图文件。
要获得以上配套资源,请在异步社区本书页面中单击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。
如果您是教师,希望获得教学配套资源,请在社区本书页面中直接联系本书的责任编辑。
您还可以扫码右侧二维码, 关注【异步社区】微信公众号,回复“e58713”直接获取,同时可以获得异步社区15天VIP会员卡,近千本电子书免费畅读。
作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。
当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,单击“图书勘误”“发表勘误”,输入勘误信息,点击“提交勘误”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。
扫描下方二维码,您将会在异步社区微信服务号中看到本书信息及相关的服务提示。
我们的联系邮箱是contact@epubit.com.cn。
如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。
如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/selfpublish/submission即可)。
如果您是学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。
如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。
“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。
“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。
异步社区
微信服务号
在介绍数据可视化之前,我们有必要对“数据科学”进行简单的介绍,这样才能站在更高的角度来理解可视化与数据科学其余各部分之间的关系。
网络爬虫、数据分析、数据可视化、机器学习……
在平常的学习或工作中,我们或多或少都听过上面这些名词。其实这些名词本身就属于数据科学概念的一部分,它们背后其实是有深层联系的。大家可能都知道,如果想从数据中提炼有用的信息,一般流程是下面这样的。
获取数据→处理数据→展示数据
网络爬虫用于获取数据,数据分析用于处理数据,数据可视化用于展示数据。而机器学习则用于进一步对数据进行建模,以便对未来的一些东西进行预测。
所谓数据科学,用简单的一句话来说就是“处理数据的科学”。对于数据科学来说,它的工作流可以总结成“OSEMN”,如表1-1和图1-1所示。
表1-1 数据科学工作流
步骤 |
常用库 |
Obtain(获取) |
Scrapy |
Scrub(清洗) |
NumPy、pandas |
Explore(展示) |
Matplotlib、Seaborn |
Model(建模) |
scikit-learn、SciPy、TensorFlow |
iNterpret(解析) |
Bokeh、D3.js |
图1-1 数据科学工作流
图1-1是一张非常有价值的图,从中我们可以得到2个非常重要的信息:①Python不同领域之间的关系;②Python不同领域用到的库。有了这张图,我们在接触Python各个领域的时候,就会有清晰的学习路线。
数据可视化,也就是数据科学中的“Explore”(展示)这一环节。对于数据来说,我们仅从它本身很难看出背后有什么规律。如果将数据以图表的方式来展示,就可以明确地发现很多有用的信息。
比如想要查看某个城市一天的气温变化,仅仅通过查看数据,并不容易看出其中的变化趋势。如果把数据以折线图的方式展示出来,趋势就会变得非常直观,如图1-2所示。
图1-2 乌鲁木齐气温变化折线图
所谓数据可视化,指的就是将数据以图表的方式展示处理。Python的可视化库有数十种之多,不过本书只会介绍常用的3个库:Matplotlib、Seaborn、Pyecharts。实际上,如果小伙伴们能熟练掌握这3个库,就基本能够满足90%以上的开发需求了。
在本书中,我们分3个部分来为小伙伴们详细介绍。
我们建议的学习顺序如图1-3所示。在学习数据可视化之前,小伙伴们一定要有数据分析的基础,不然学习起来是比较吃力的。那怎样才算有数据分析基础呢?其实很简单,你至少要掌握NumPy和pandas这两个库。NumPy和pandas是数据分析中非常重要的两个库。
图1-3 学习顺序
可能有小伙伴会问,为什么一定要有数据分析基础呢?就拿后面介绍的Seaborn这个库来说,它就要求数据必须是序列(Series)或数据帧(DataFrame)。而它们恰恰都是pandas的数据格式。如果你没有学习过数据分析,可以说是很难明白Seaborn的语法的。
由于从0到1这个系列的书都是我一个人写的,所以我已经替小伙伴们考虑过了。没有数据分析基础的小伙伴,可以看一下本系列的《从0到1——Python数据分析》。它和本书具有比较强的连贯性,可以让你把数据分析和数据可视化理解得更加透彻。
关于Matplotlib、Seaborn、Pyecharts,我们约定统一采用首字母大写的方式来表示。(虽然官网有些使用大写,有些使用小写,不过这样会非常混乱。)这一点小伙伴们了解一下就可以了。
此外对于开发工具,我们推荐使用下面这3种(任意一种都可以)。对于这些开发工具的安装和使用,由于在本系列其他书中已经介绍得非常多了,这里就不再展开介绍。
● VS Code。
● PyCharm。
● Jupyter Notebook。
微信扫码关注【异步社区】微信公众号,回复“e58713”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。
在Python中,我们可以使用Matplotlib这个库来实现数据可视化。在众多可视化库中,Matplotlib是非常基础的一个,后面介绍的Seaborn也是基于Matplotlib来实现的。可以这样说,如果你想要学习数据可视化,那么Matplotlib是必学的一个。
Matplotlib(如图2-1所示)是基于NumPy实现的一个库。它借鉴了很多MATLAB中的函数,使我们可以轻松绘制各种高质量的图表,包括折线图、散点图、柱形图等。此外,应用Matplotlib不仅可以绘制二维图,还可以绘制三维图,以及实现各种图形动画等。
图2-1 Matplotlib
由于Matplotlib是第三方库,因此我们需要手动安装该库。如果小伙伴们使用的是VS Code,打开终端窗口并输入下面的命令,按“Enter”键即可安装该库。
pip install matplotlib
如果想要使用Matplotlib来绘制各种图表,我们可以借助它的pyplot子库中的各种绘图函数来实现,常用的绘图函数如表2-1所示。
表2-1 Matplotlib常用图表的绘图函数
基础图表 |
绘图函数 |
折线图 |
plot() |
柱形图 |
bar() |
条形图 |
barh() |
直方图 |
hist() |
饼状图 |
pie() |
散点图 |
scatter() |
箱线图 |
boxplot() |
高级图表 |
绘图函数 |
阶梯图 |
step() |
面积图 |
stackplot() |
棉棒图 |
stem() |
误差棒图 |
errorbar() |
雷达图 |
polar() |
热力图 |
imshow() |
子图表 |
subplot() |
每一个绘图函数提供的参数都是非常多的,为了让小伙伴们能快速理解以及减轻记忆负担,我们只介绍常用的参数。如果想要更深入地了解每一个函数的功能,小伙伴们还是要多查阅一下Matplotlib的官方文档。
最后需要特别说明一点,如果大家看过《从0到1——Python数据分析》一书,就知道其实里面已经介绍过Matplotlib了。但是由于Matplotlib是后面介绍的Seaborn的实现基础,并且考虑到很多小伙伴可能没有看过从0到1系列的其他书,因此这里还是先详细介绍一下Matplotlib的使用方法。当然,由于本书是专门介绍数据可视化的,因此书中涉及的技术细节也会较深入、全面。
Matplotlib非常基础的应用就是绘制折线图。本节我们先简单介绍一下如何绘制折线图,再介绍如何绘制其他图表。
在Matplotlib中,可以使用plot()函数来绘制折线图。折线图的主要作用是表现“因变量y”随着“自变量x”改变的趋势。所以折线图特别适用于展示随时间变化的连续数据。
plt.plot(x, y)
x和y都是必选参数,它们可以是列表、数组、序列(Series)以及其他可迭代对象(比如range对象)。其中,数组是NumPy的数据类型,Series是pandas的数据类型。
# 导入库
import matplotlib.pyplot as plt
# 绘图
x = [1, 2, 3, 4]
y = [16, 15, 18, 17]
plt.plot(x, y)
# 显示
plt.show()
运行之后,效果如图2-2所示。
图2-2 一条折线
如果想要使用Matplotlib来绘制图表,我们至少要经历3步:①导入库;②绘图;③显示。
# 第1步:导入库
import matplotlib.pyplot as plt
首先,我们使用上面这句代码来导入Matplotlib库中的pyplot子库,并将其命名为plt。因为Matplotlib大部分的绘图功能集成在pyplot子库中,所以通常只需要导入pyplot子库就可以了。
# 第2步:绘图
x = [1, 2, 3, 4]
y = [16, 15, 18, 17]
plt.plot(x, y)
接下来,我们使用上面的代码来绘制一个折线图。根据x和y这两个列表可知,该图有4个折点坐标:(1, 16)、(2, 15)、(3, 18)、(4, 17)。
# 第3步:显示
plt.show()
只有第1步和第2步,运行代码之后并不会有任何效果。最后我们还要调用pyplot的show()函数,这样才能把图表显示出来。
Matplotlib窗口除了可展示图表之外,还提供了很多便捷的功能,其工具栏如图2-3所示。工具栏涉及的功能包括保存成一张图片、对窗口进行配置等,小伙伴们可以自行探索。
图2-3 工具栏
import matplotlib.pyplot as plt
# 绘图
x1 = [1, 2, 3, 4]
y1 = [16, 15, 18, 17]
x2 = [1, 2, 3, 4]
y2 = [15, 19, 17, 16]
plt.plot(x1, y1)
plt.plot(x2, y2)
# 显示
plt.show()
运行之后,效果如图2-4所示。
图2-4 多条折线
在一个折线图中,我们不仅可以绘制一条折线,还可以同时绘制多条折线。在一个折线图中绘制多条折线也很简单,只需要多次调用plot()函数就可以了。
实际上,我们调用一次plot()函数也能绘制多条折线。对于这个例子来说,下面2种形式是等价的。
# 形式1:调用多次plot()
plt.plot(x1, y1)
plt.plot(x2, y2)
# 形式2:调用一次plot()
plt.plot(x1, y1, x2, y2)
为了让折线图更加美观,plot()函数还提供了很多用于定义样式的参数,这些参数主要分为2类:① 线条样式参数;② 节点样式参数。
在Matplotlib中,用于定义线条样式的参数有3个,如表2-2所示。
表2-2 线条样式参数
参数 |
说明 |
color |
线条颜色 |
linestyle |
线条外观 |
linewidth |
线条宽度 |
参数color用于定义线条的颜色,它常用的取值有2种:① 关键字(又称关键词);② 十六进制RGB值。其中,关键字指的是颜色的英文名称,比如red、green、blue等;而十六进制RGB值指的是类似“#FBF9D0”这样的值。
如果使用关键字满足不了需求,我们就要借助十六进制RGB值,相信经常使用Photoshop的小伙伴对这种值不会陌生。可能有小伙伴会问:这种十六进制RGB值是怎么获取的呢?
我们可以使用一个名为“Color Express”的软件(如图2-5所示),来获取十六进制RGB值。
图2-5 Color Express
参数linestyle用于定义线条的外观,它常用的取值有2种:① 关键字;② 字符。具体内容如表2-3所示。
表2-3 参数linestyle的常用取值
关键字 |
|
solid(默认值) |
实线 |
dashed |
虚线 |
dotted |
点线 |
dashdot |
点划线 |
字符 |
|
-(默认值) |
实线 |
-- |
虚线 |
: |
点线 |
-. |
点划线 |
参数linewidth用于定义线条的宽度,比如linewidth=2表示定义线条宽度为2像素。linewidth的默认值为1,也就是1像素。
import matplotlib.pyplot as plt
# 绘图
x = [1, 2, 3, 4]
y = [16, 15, 18, 17]
plt.plot(x, y, color="red")
# 显示
plt.show()
运行之后,效果如图2-6所示。
图2-6 红色线条
plt.plot(x, y, color="red")这句代码表示定义线条颜色为red(红色),当然我们也可以使用十六进制RGB值,小伙伴们可以自行尝试。
# 十六进制RGB值
plt.plot(x, y, color="#10CBC8")
import matplotlib.pyplot as plt
# 绘图
x = [1, 2, 3, 4]
y = [16, 15, 18, 17]
plt.plot(x, y, linestyle="dashed")
# 显示
plt.show()
运行之后,效果如图2-7所示。
图2-7 虚线
对于这个例子来说,下面2种形式是等价的。另外对于参数linestyle其他取值的效果,小伙伴们可以自行尝试。
# 形式1
plt.plot(x, y, linestyle="dashed")
# 形式2
plt.plot(x, y, linestyle="--")
import matplotlib.pyplot as plt
# 绘图
x = [1, 2, 3, 4]
y = [16, 15, 18, 17]
plt.plot(x, y, linewidth=3)
# 显示
plt.show()
运行之后,效果如图2-8所示。
图2-8 改变线条宽度
在这个例子中,linewidth=3表示定义线条的宽度为3像素。
在Matplotlib中,用于定义节点样式的参数有4个,如表2-4所示。
表2-4 节点样式参数
参数 |
说明 |
marker |
节点外观 |
markersize或ms |
节点大小 |
markerfacecolor或mfc |
节点颜色 |
markeredgecolor或mec |
边框颜色 |
参数marker用于定义节点的外观,它常用的取值如表2-5所示。
表2-5 参数marker的常用取值
取值 |
说明 |
. |
点 |
, |
像素 |
o |
实心圆 |
v |
下三角形 |
^ |
上三角形 |
< |
左三角形 |
> |
右三角形 |
1 |
下花三角形 |
2 |
上花三角形 |
3 |
左花三角形 |
4 |
右花三角形 |
s |
实心正方形 |
p |
实心五角星形 |
* |
星形 |
h |
竖六边形 |
H |
横六边形 |
+ |
加号 |
x |
叉号 |
d |
小菱形 |
D |
大菱形 |
| |
垂直线条 |
参数marker的取值非常多,我们并不需要都记住,在实际开发中需要用到的时候查阅一下表2-5就可以了。
参数markersize用于定义节点的大小,它可以简写为“ms”。参数markerfacecolor用于定义节点的颜色,它可以简写为“mfc”。参数markeredgecolor用于定义边框的颜色,它可以简写为“mec”。
import matplotlib.pyplot as plt
# 绘图
x = [1, 2, 3, 4]
y = [16, 15, 18, 17]
plt.plot(x, y, marker="o")
# 显示
plt.show()
运行之后,效果如图2-9所示。
图2-9 节点为实心圆
把节点定义成实心圆,我们知道怎么实现了。如果想要把节点定义成空心圆,又该怎么做呢?我们只需要将markerfacecolor设置为white(白色)就可以了,代码如下。
plt.plot(x, y, marker="o", markerfacecolor="white") # 节点为空心圆
再次运行之后,效果如图2-10所示。
图2-10 节点为空心圆
import matplotlib.pyplot as plt
# 绘图
x = [1, 2, 3, 4]
y = [16, 15, 18, 17]
plt.plot(x, y, marker="o", markersize=10)
# 显示
plt.show()
运行之后,效果如图2-11所示。
图2-11 改变节点大小
在这个例子中,markersize=10表示定义节点大小为10像素。由于markersize可以简写为ms,所以下面2种形式是等价的。
# 形式1
plt.plot(x, y, marker="o", markersize=10)
# 形式2
plt.plot(x, y, marker="o", ms=10)
import matplotlib.pyplot as plt
# 绘图
x = [1, 2, 3, 4]
y = [16, 15, 18, 17]
plt.plot(x, y, marker="o", markersize=10, markerfacecolor="orange", markeredgecolor="red")
# 显示
plt.show()
运行之后,效果如图2-12所示。
图2-12 改变节点颜色
在这个例子中,markerfacecolor="orange"表示定义节点颜色为“orange”(橙色),markeredgecolor="red"表示定义边框颜色为“red”(红色)。
由于markerfacecolor可以简写为mfc,而markeredgecolor可以简写为mec,所以对于这个例子来说,下面2种形式是等价的。
# 形式1
plt.plot(x, y, marker="o", markersize=10, markerfacecolor="orange", markeredgecolor="red")
# 形式2
plt.plot(x, y, marker="o", markersize=10, mfc="orange", mec="red")
最后需要说明一点,数据可视化的目的是绘制出使用户体验更好的图表,所以大多数可视化库都会提供各种用于自定义样式的方法或参数,这样做的目的是方便开发者实现定制化程度更高的图表。所以我们在学习可视化库的时候,除了学习如何绘制基础图表之外,更多的是学习各种样式的定义方法。了解这一点,可以让我们的学习思路变得更加清晰。
本书所有例子使用的数据集文件(一般是CSV文件)都可以在本书配套资源中找到。对于这一点,后面就不再重复说明了。
首先创建一个名为“data”的文件夹,然后在该文件夹中创建一个guangzhou.csv文件,项目结构如图2-13所示。其中,guangzhou.csv文件保存的是广州一年内每个月的最高气温和最低气温数据,如图2-14所示。
图2-13 项目结构
图2-14 guangzhou.csv文件内容
import pandas as pd
import matplotlib.pyplot as plt
# 读取数据
df = pd.read_csv(r"data/guangzhou.csv")
plt.plot(df["月份"], df["最高"], marker="o", markerfacecolor="white")
plt.plot(df["月份"], df["最低"], marker="o", markerfacecolor="white")
# 显示
plt.show()
运行之后,效果如图2-15所示。
图2-15 广州气温折线图
对于plt.plot(x, y)来说,x和y除了可以是列表之外,还可以是Series。大家应该都知道,DataFrame的一列本质上就是一个Series。小伙伴们要记住这一点:在Matplotlib中,大多数绘图函数的数据除了可以是列表,还可以是Series。
Series和DataFrame是pandas的数据结构,这些都是数据分析的基础。这也是我们在一开始就强调一定要先学习数据分析,然后再学习数据可视化的原因,不然很多内容会理解不了。
在介绍如何绘制其他图表之前,我们先来介绍一下通用的设置。这些设置不仅可以用于折线图,也可以用于大多数其他图表。与通用设置相关的大多数函数是直接通过pyplot子库来调用的,这一点大家一定要清楚。
import matplotlib.pyplot as plt
plt.函数名()
在Matplotlib中,用于通用设置的函数比较多,常用的如表2-6所示。本节的内容很重要,也是学习后面章节的基础,小伙伴们要认真掌握。
表2-6 通用设置函数
函数 |
说明 |
figure() |
画布样式 |
title()、xlabel()、ylabel() |
定义标题 |
legend() |
定义图例 |
xticks()、yticks() |
刻度标签 |
xlim()、ylim() |
刻度范围 |
grid() |
网格线 |
axhline()、axvline() |
参考线 |
axhspan()、axvspan() |
参考区域 |
annotate() |
注释内容(有指向) |
text() |
注释内容(无指向) |
在Matplotlib中,我们可以使用figure()函数来定义画布的样式,包括画布的大小、画布的颜色、边框颜色等。
plt.figure(figsize, facecolor, edgecolor)
参数figsize用于定义画布的大小,它的取值是元组,比如figsize=(10, 20)表示宽度为10英寸(1英寸=2.54厘米)、高度为20英寸。
参数facecolor用于定义画布的颜色,参数edgecolor用于定义边框颜色。它们的取值可以是关键字,也可以是十六进制RGB值。
import matplotlib.pyplot as plt
# 画布样式
plt.figure(figsize=(5, 4), facecolor="lightskyblue")
# 绘图
x = [1, 2, 3, 4]
y = [16, 15, 18, 17]
plt.plot(x, y)
# 显示
plt.show()
运行之后,效果如图2-16所示。
图2-16 画布样式
我们要特别注意一点,由于画布样式针对的是全局,所以figure()函数必须在绘图函数之前调用,不然就会出现问题。小伙伴们可以试一下把figure()函数放在plot()函数之后调用,看看效果是怎样的。
除了figure()函数比较特殊之外,对于其他通用设置函数,如果没有特别说明,那么它们既可以在绘图函数之前调用,也可以在绘图函数之后调用。
在Matplotlib中,我们可以使用title()、xlabel()、ylabel()这3个函数来分别定义主标题、x轴标题和y轴标题。
plt.title(label, loc) # 主标题
plt.xlabel(label, loc) # x轴标题
plt.ylabel(label, loc) # y轴标题
title()、xlabel()、ylabel()这3个函数都有label和loc这2个参数。label用于定义标题内容,而loc用于定义标题位置。不同函数的loc参数的取值是不一样的,说明分别如下。
● 对于title()来说,它的loc参数取值有3个:left、center、right。
● 对于xlabel()来说,它的loc参数取值有3个:left、center、right。
● 对于ylabel()来说,它的loc参数取值有3个:top、center、bottom。
import matplotlib.pyplot as plt
# 解决中文乱码问题
plt.rcParams["font.family"] = ["SimHei"]
# 解决负号不显示问题
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = [1, 2, 3, 4]
y = [16, 15, 18, 17]
plt.plot(x, y)
# 定义标题
plt.title("一个折线图")
plt.xlabel("x轴标题")
plt.ylabel("y轴标题")
# 显示
plt.show()
运行之后,效果如图2-17所示。
图2-17 常规设置的标题
如果图表中包含中文,就必须使用plt.rcParams["font.family"]来设置中文字体,不然就会出现乱码问题。如果图表中包含符号“-”,就必须设置plt.rcParams["axes.unicode_minus"]为False。
在实际工作中,建议在绘图代码的开始处统一加上下面这两句代码。
plt.rcParams["font.family"] = ["SimHei"] # 解决中文乱码问题
plt.rcParams["axes.unicode_minus"] = False # 解决负号不显示问题
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = [1, 2, 3, 4]
y = [16, 15, 18, 17]
plt.plot(x, y)
# 定义标题
plt.title("一个折线图", loc="left")
plt.xlabel("x轴标题")
plt.ylabel("y轴标题")
# 显示
plt.show()
运行之后,效果如图2-18所示。
图2-18 改变主标题位置
在这个例子中,title()函数中的loc="left"表示定义主标题的位置在左边。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = [1, 2, 3, 4]
y = [16, 15, 18, 17]
plt.plot(x, y)
# 定义标题
plt.title("一个折线图")
plt.xlabel("x轴标题", loc="right")
plt.ylabel("y轴标题", loc="top")
# 显示
plt.show()
运行之后,效果如图2-19所示。
图2-19 改变x、y轴标题位置
x轴标题默认是水平居中的,如果想要将其定义到最右边,我们可以使用loc="right"来实现。而y轴标题默认是垂直居中的,如果想要将其定义到最顶部,我们可以使用loc="top"来实现。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = [1, 2, 3, 4]
y = [16, 15, 18, 17]
plt.plot(x, y)
# 定义标题
plt.title("一个折线图", fontsize=14, color="red")
plt.xlabel("x轴标题")
plt.ylabel("y轴标题")
# 显示
plt.show()
运行之后,效果如图2-20所示。
图2-20 定义字体样式
标题本质上是文本,既然是文本,我们就可以使用fontsize、color等参数定义样式。其中fontsize用于定义文字大小,color用于定义文字颜色。
对于这个例子来说,fontsize=14表示定义文字大小为14像素,color="red"表示定义文字颜色为红色。当然,小伙伴们也可以自行尝试在xlabel()和ylabel()函数中设置参数。
在Matplotlib中,我们可以使用legend()函数来为图表定义图例。
plt.legend(loc)
参数loc用于定义图例的位置,loc是“location”的缩写,它常用的取值如表2-7所示,对应的图示如图2-21所示。
表2-7 参数loc的常用取值
取值 |
说明 |
upper left |
左上 |
upper center |
靠上居中 |
upper right |
右上 |
center left |
居中靠左 |
center |
正中 |
center right |
居中靠右 |
lower left |
左下 |
lower center |
靠下居中 |
lower right |
右下 |
图2-21 参数loc的取值对应的图示
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x1 = [1, 2, 3, 4]
y1 = [16, 15, 18, 17]
x2 = [1, 2, 3, 4]
y2 = [15, 19, 17, 16]
plt.plot(x1, y1, label="折线A")
plt.plot(x2, y2, label="折线B")
# 定义图例
plt.legend()
# 显示
plt.show()
运行之后,效果如图2-22所示。
图2-22 定义图例
由于legend()函数需要结合绘图函数的label参数一起使用,所以legend()函数必须在绘图函数的后面调用,不然就无法生效。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x1 = [1, 2, 3, 4]
y1 = [16, 15, 18, 17]
x2 = [1, 2, 3, 4]
y2 = [15, 19, 17, 16]
plt.plot(x1, y1, label="折线A")
plt.plot(x2, y2, label="折线B")
# 定义图例
plt.legend(loc="upper left")
# 显示
plt.show()
运行之后,效果如图2-23所示。
图2-23 改变图例位置
plt.legend(loc="upper left")表示将图例定义在图表的左上角处。
有些情况下,坐标轴默认的刻度标签并不能满足我们的开发需求。在Matplotlib中,我们可以使用xticks()函数来定义x轴的刻度标签,也可以使用yticks()函数来定义y轴的刻度标签。
plt.xticks(ticks, labels)
plt.yticks(ticks, labels)
xticks()和yticks()都可以接收2个参数,ticks和labels都是列表或可迭代对象(如range对象)。ticks是必选参数,表示刻度值。labels是可选参数,表示标签值。其中labels是与ticks一一对应的。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = range(1, 16)
y = [36.0, 36.1, 36.6, 36.2, 36.4, 36.5, 36.0, 36.2, 36.4, 36.8, 36.7, 36.1, 36.6, 36.5, 36.7]
plt.plot(x, y, marker="o", markerfacecolor="white") # 节点为空心圆
# 定义标题
plt.title("15日体温变化")
plt.xlabel("日期")
plt.ylabel("体温")
# 显示
plt.show()
运行之后,效果如图2-24所示。
图2-24 默认效果
从图2-24可以看出,x轴的刻度是2、4、6……这样的数字,但是我们想要1、2、3、4……这样更加精确的刻度,此时就可以使用xticks()函数来实现。
plt.xticks(ticks=range(1, 16))
把上面这句代码加到“举例”中的“定义标题”的后面,再次运行之后,效果如图2-25所示。
图2-25 改变刻度
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = range(1, 16)
y = [36.0, 36.1, 36.6, 36.2, 36.4, 36.5, 36.0, 36.2, 36.4, 36.8, 36.7, 36.1, 36.6, 36.5, 36.7]
plt.plot(x, y, marker="o", markerfacecolor="white") # 节点为空心圆
# 定义标题
plt.title("15日体温变化")
plt.xlabel("日期")
plt.ylabel("体温")
# 刻度标签
dates = [str(i)+"日" for i in range(1, 16)]
plt.xticks(ticks=range(1, 16), labels=dates)
# 显示
plt.show()
运行之后,效果如图2-26所示。
图2-26 定义labels效果
dates=[str(i)+"日" for i in range(1, 16)]这一句代码使用了列表生成式的语法,主要用于快速生成这样一个列表:["1日", "2日", ... , "15日"]。列表生成式的使用属于Python进阶技巧,小伙伴们可以自行搜索了解或看一下本系列书中的《从0到1——Python进阶之旅》。
对于plt.xticks(ticks, labels)来说,如果想要使用第2个参数,那么ticks和labels这2个列表的元素个数必须相同,labels的元素会一一替换到ticks表示的刻度上。
刻度范围指的是坐标轴的取值范围,包括x轴和y轴的取值范围。刻度范围是否合理,会直接影响图表展示的效果。
在Matplotlib中,我们可以使用xlim()函数来定义x轴的范围,使用ylim()函数来定义y轴的范围。
plt.xlim(left, right)
plt.ylim(left, right)
xlim()和ylim()的取值范围为[left, right],这个范围包括left也包括right。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = range(1, 16)
y = [36.0, 36.1, 36.6, 36.2, 36.4, 36.5, 36.0, 36.2, 36.4, 36.8, 36.7, 36.1, 36.6, 36.5, 36.7]
plt.plot(x, y, marker="o", markerfacecolor="white") # 节点为空心圆
# 定义标题
plt.title("15日体温变化")
plt.xlabel("日期")
plt.ylabel("体温")
# 刻度范围
plt.xlim(1, 14)
plt.ylim(35, 45)
# 显示
plt.show()
运行之后,效果如图2-27所示。
图2-27 改变刻度范围
刻度标签和刻度范围是不一样的,刻度标签是一一对应到坐标轴上的,而刻度范围仅仅是定义一个范围,刻度是由Matplotlib自动调整或人工手动调整得到的。对于这两个概念,小伙伴们可以多多对比一下,它们其实并不难理解。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = range(1, 16)
y = [36.0, 36.1, 36.6, 36.2, 36.4, 36.5, 36.0, 36.2, 36.4, 36.8, 36.7, 36.1, 36.6, 36.5, 36.7]
plt.plot(x, y, marker="o", markerfacecolor="white") # 节点为空心圆
# 定义标题
plt.title("15日体温变化")
plt.xlabel("日期")
plt.ylabel("体温")
# 逆序排列
plt.xlim(15, 1)
# 显示
plt.show()
运行之后,效果如图2-28所示。
图2-28 逆序排列
在这个例子中,我们使用xlim()函数将“日期”的刻度标签值逆序排列。实现方式很简单,只需要将原来xlim(left, right)中的left和right这两个参数调换位置就可以了。
在Matplotlib中,我们可以使用grid()函数来给图表添加网格线效果。
plt.grid(axis, linestyle, color)
参数axis表示显示哪个方向的网格线,它的常用取值有3种,如表2-8所示。
表2-8 参数axis的常用取值
取值 |
说明 |
both(默认值) |
显示两个方向的网格线 |
x |
显示水平方向的网格线 |
y |
显示垂直方向的网格线 |
参数linestyle用于定义网格线的外观,它的取值和绘制折线图时涉及的linestyle参数的取值是一样的,如表2-9所示(与表2-3相同,为方便小伙伴们,在此处重复使用一次)。
表2-9 参数linestyle的常用取值
关键字 |
|
solid(默认值) |
实线 |
dashed |
虚线 |
dotted |
点线 |
dashdot |
点划线 |
字符 |
|
-(默认值) |
实线 |
-- |
虚线 |
: |
点线 |
-. |
点划线 |
参数color用于定义网格线的颜色,它的取值可以是关键字,也可以是十六进制RGB值。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = range(1, 16)
y = [36.0, 36.1, 36.6, 36.2, 36.4, 36.5, 36.0, 36.2, 36.4, 36.8, 36.7, 36.1, 36.6, 36.5, 36.7]
plt.plot(x, y, marker="o", markerfacecolor="white")
# 定义标题
plt.title("15日体温变化")
plt.xlabel("日期")
plt.ylabel("体温")
# 网格线
plt.grid(axis="both", linestyle="dashed", color="orangered")
# 显示
plt.show()
运行之后,效果如图2-29所示。
图2-29 显示两个方向的网格线
plt.grid(axis="both", linestyle="dashed", color="orangered")表示定义两个方向的网格线,其中网格线的外观是“dashed”(虚线),颜色为“orangered”(橙红色)。
如果使用axis="x",效果如图2-30所示。如果使用axis="y",效果如图2-31所示。
图2-30 水平方向的网格线
图2-31 垂直方向的网格线
在Matplotlib中,我们可以使用axhline()函数来添加水平方向的参考线,也可以使用axvline()函数来添加垂直方向的参考线。
其中,axhline是“axis horizontal line”(水平参考线)的缩写,axvline是“axis vertical line”(垂直参考线)的缩写。
plt.axhline(y, color, linestyle, linewidth)
plt.axvline(x, color, linestyle, linewidth)
x和y用于定义参考线的方向,color用于定义参考线的颜色,linestyle用于定义参考线的风格,linewidth用于定义参考线的宽度。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = range(1, 16)
y = [36.0, 36.1, 36.6, 36.2, 36.4, 36.5, 36.0, 36.2, 36.4, 36.8, 36.7, 36.1, 36.6, 36.5, 36.7]
plt.plot(x, y, marker="o", markerfacecolor="white")
# 定义标题
plt.title("15日体温变化")
plt.xlabel("日期")
plt.ylabel("体温")
# 水平参考线
plt.axhline(y=36.5, color="red", linestyle="dashed", linewidth=1)
# 显示
plt.show()
运行之后,效果如图2-32所示。
图2-32 axhline()定义水平参考线
如果想要同时添加多条水平参考线,只需要多次调用axhline()函数就可以了。比如将“#水平参考线”部分的代码替换为下面2句代码,运行效果如图2-33所示。
plt.axhline(y=36.8, color="red", linestyle="dashed", linewidth=1)
plt.axhline(y=36.0, color="red", linestyle="dashed", linewidth=1)
图2-33 多条水平参考线
如果想要添加一条垂直方向的参考线,我们可以使用axvline()函数来实现。比如将“#水平参考线”部分的代码改为下面这一句代码,运行效果如图2-34所示。
plt.axvline(x=10, color="red", linestyle="dashed", linewidth=1)
图2-34 axvline()定义垂直参考线
在Matplotlib中,我们可以使用axhspan()函数添加水平方向的参考区域,也可以使用axvspan()函数添加垂直方向的参考区域。
其中,axhspan是“axis horizontal span”(水平参考区域)的缩写,axvspan是“axis vertical span”(垂直参考区域)的缩写。
plt.axhspan(ymin, ymax, facecolor, alpha)
plt.axvspan(xmin, xmax, facecolor, alpha)
xmin或ymin用于定义区域的开始坐标,xmax或ymax用于定义区域的结束坐标,facecolor用于定义区域颜色,alpha用于定义透明度(0.0~1.0)。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = range(1, 16)
y = [36.0, 36.1, 36.6, 36.2, 36.4, 36.5, 36.0, 36.2, 36.4, 36.8, 36.7, 36.1, 36.6, 36.5, 36.7]
plt.plot(x, y, marker="o", markerfacecolor="white")
# 定义标题
plt.title("15日体温变化")
plt.xlabel("日期")
plt.ylabel("体温")
# 水平参考区域
plt.axhspan(ymin=36.4, ymax=36.6, facecolor="red", alpha=0.2)
# 显示
plt.show()
运行之后,效果如图2-35所示。
图2-35 axhspan()定义水平参考区域
如果想要添加一个垂直方向的参考区域,我们可以使用axvspan()函数来实现。比如将“#水平参考区域”部分的代码改为下面这一句代码,运行效果如图2-36所示。
plt.axvspan(xmin=5, xmax=10, facecolor="red", alpha=0.2)
图2-36 axvspan()定义垂直参考区域
在Matplotlib中,我们可以使用annotate()函数为一些关键节点添加有指向的注释文本。
plt.annotate(text, xy, xytext, arrowprops)
text表示注释文本的内容,xy表示注释节点的坐标(元组型),xytext表示注释文本的坐标(元组型),arrowprops表示箭头的样式。
其中arrowprops的值是一个字典,它常用的键(key)包括color、width、headwidth、headlength、shrink、arrowstyle等。其中,arrowstyle用于定义箭头的类型,其常用取值如表2-10所示。
表2-10 arrowstyle的常用取值
取值 |
形状 |
- |
|
-> |
|
<- |
|
<-> |
|
-|> |
|
<|- |
|
<|-|> |
|
-[ |
|
|-| |
|
simple |
|
fancy |
|
wedge |
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = range(1, 16)
y = [36.0, 36.1, 36.6, 36.2, 36.4, 36.5, 36.0, 36.2, 36.4, 36.8, 36.7, 36.1, 36.6, 36.5, 36.7]
plt.plot(x, y, marker="o", markerfacecolor="white")
# 定义标题
plt.title("15日体温变化")
plt.xlabel("日期")
plt.ylabel("体温")
# 添加注释
plt.annotate(
text="最高体温",
xy=(10, 36.8),
xytext=(6, 36.6),
arrowprops={"arrowstyle": "->"}
)
# 显示
plt.show()
运行之后,效果如图2-37所示。
图2-37 注释文本(有指向)
需要注意的是,xy是注释节点的坐标,而xytext是注释文本的坐标。xytext一般要设置得与xy有一定距离,不然就可能会重叠。
默认情况下,注释文本和箭头都是黑色,我们可以对它们分别定义颜色。修改“#添加注释”部分的代码如下,运行效果如图2-38所示。
plt.annotate(
text="最高体温",
xy=(10, 36.8),
xytext=(6, 36.6),
color="red",
arrowprops={"arrowstyle": "->", "color": "red"}
)
图2-38 定义颜色
在Matplotlib中,我们可以使用text()函数给节点添加注释文本。这种方式可以让图表数据展示得更加直观。
plt.text(x, y, text)
x是x轴坐标,y是y轴坐标,text是注释文本。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = range(1, 16)
y = [36.0, 36.1, 36.6, 36.2, 36.4, 36.5, 36.0, 36.2, 36.4, 36.8, 36.7, 36.1, 36.6, 36.5, 36.7]
plt.plot(x, y, marker="o", markerfacecolor="white")
# 定义标题
plt.title("15日体温变化")
plt.xlabel("日期")
plt.ylabel("体温")
# 注释文本
plt.text(10, 36.8, "最高")
plt.text(1, 36.0, "最低")
# 显示
plt.show()
运行之后,效果如图2-39所示。
图2-39 注释文本(无指向)
annotate()函数添加的是有指向的注释文本,也就是有箭头之类的指向标识。而text()函数添加的是无指向的注释文本,也就是没有箭头之类的指向标识。
text()函数一次只能为一个节点添加注释文本。如果想要添加多个注释文本,我们只需要多次调用text()函数就可以了。那么如果想要为所有节点都添加注释文本,应该怎么做呢?小伙伴们可以看一下下面的例子。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = range(1, 16)
y = [36.0, 36.1, 36.6, 36.2, 36.4, 36.5, 36.0, 36.2, 36.4, 36.8, 36.7, 36.1, 36.6, 36.5, 36.7]
plt.plot(x, y, marker="o", markerfacecolor="white")
# 定义标题
plt.title("15日体温变化")
plt.xlabel("日期")
plt.ylabel("体温")
# 注释文本
for a, b in zip(x, y):
plt.text(a, b, b)
# 显示
plt.show()
运行之后,效果如图2-40所示。
图2-40 所有节点都有注释文本
for a, b in zip(x, y):
plt.text(a, b, b)
上面这一段代码表示为每一个节点添加一个注释文本,其关键在于zip()函数的巧妙应用。此外在默认情况下,注释文本的样式并不是非常美观,我们还可以使用color、fontsize等参数来自定义样式。修改后的代码如下所示。
for a, b in zip(x, y):
plt.text(a, b, b, color="red", fontsize=9, ha="center", va="bottom")
其中ha="center"表示水平居中,va="bottom"表示处于底部。再次运行之后,效果如图2-41所示。
最后要说明一点,本节介绍的这些设置,不仅可以用于折线图,也可以用于大多数其他图表,这一点小伙伴们一定要记住。
图2-41 修改样式
在Matplotlib中,有一些样式参数可以被大多数(注意是大多数,并不是所有)绘图函数使用,这些参数又叫作“通用样式参数”,详细说明如表2-11所示。
表2-11 通用样式参数
参数 |
说明 |
color |
颜色 |
fontsize |
文本大小 |
ha |
水平对齐 |
va |
垂直对齐 |
label |
图例 |
alpha |
透明度(0~1.0) |
表2-11中,ha是“horizontal align”(水平对齐)的缩写,va是“vertical align”(垂直对齐)的 缩写。
在Matplotlib中,我们可以使用scatter()函数来绘制散点图。散点图的主要作用有以下2个。
● 判断变量之间是否存在关联趋势,并判断这个关联趋势是线性的还是非线性的。
● 判断是否有离群点(也叫异常点),也就是偏移量比较大的点。
plt.scatter(x, y)
参数x存放的是所有点的x轴坐标,参数y存放的是所有点的y轴坐标,它们可以是列表、数组、Series等。
import matplotlib.pyplot as plt
# 绘图
x = [1, 2, 3, 4, 5, 6, 7, 8]
y = [15, 12, 14, 12, 11, 14, 13, 12]
plt.scatter(x, y)
# 显示
plt.show()
运行之后,效果如图2-42所示。
图2-42 基本散点图
import matplotlib.pyplot as plt
import numpy as np
# 绘图
x = np.random.randn(1000)
y = np.random.randn(1000)
plt.scatter(x, y, alpha=0.8)
# 显示
plt.show()
运行之后,效果如图2-43所示。
图2-43 正态分布散点图
np.random.randn(1000)用于生成1000个符合正态分布的样本数据。
为了让散点图更加美观,scatter()函数还提供了很多用于定义样式的参数,常用的如表2-12所示。
表2-12 scatter()函数定义样式的参数
参数 |
说明 |
marker |
散点的形状 |
s |
散点的大小(指size) |
color |
散点的颜色 |
alpha |
散点的透明度(0.0~1.0) |
import matplotlib.pyplot as plt
# 绘图
x= [1, 2, 3, 4, 5, 6, 7, 8]
y = [15, 12, 14, 12, 11, 14, 13, 12]
plt.scatter(x, y, marker="x")
# 显示
plt.show()
运行之后,效果如图2-44所示。
图2-44 改变散点的形状
marker="x"用于定义散点的形状为“x”。marker参数的取值非常多,它的取值和绘制折线图的plot()函数的marker参数的取值是一样的,小伙伴们可以回顾一下“2.2 基础绘图(折线图)”这一节。
import matplotlib.pyplot as plt
# 绘图
x= [1, 2, 3, 4, 5, 6, 7, 8]
y = [15, 12, 14, 12, 11, 14, 13, 12]
plt.scatter(x, y, s=80, color="red", alpha=0.3)
# 显示
plt.show()
运行之后,效果如图2-45所示。
图2-45 改变散点的大小、颜色、透明度
plt.scatter(x, y, s=80, color="red", alpha=0.3)表示定义散点的大小为80、颜色为红色、透明度为0.3。
在当前项目下的data文件夹中有一个clothes.csv文件,项目结构如图2-46所示。其中,clothes.csv文件保存的是某服装店一年内每个月的上衣和裤子的销量(单位:件)数据,内容如图2-47所示。
图2-46 项目结构
图2-47 clothes.csv文件内容
import pandas as pd
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 读取数据
df = pd.read_csv(r"data/clothes.csv")
# 绘制图表
plt.scatter(df["月份"], df["上衣"])
# 显示
plt.show()
运行之后,效果如图2-48所示。
图2-48 一组散点
import pandas as pd
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 读取数据
df = pd.read_csv(r"data/clothes.csv")
# 绘制图表
plt.scatter(df["月份"], df["上衣"])
plt.scatter(df["月份"], df["裤子"], marker="v")
# 显示
plt.show()
运行之后,效果如图2-49所示。
图2-49 多组散点
想要同时绘制多组散点,我们只需要多次调用scatter()函数就可以了。当然,为了区分不同的组,我们可以通过设置marker来改变散点的外观。
在Matplotlib中,我们可以使用scatter()函数的s参数来绘制气泡图。需要注意的是,此时s参数的值要求是一个列表。
import matplotlib.pyplot as plt
# 绘图
x = range(1,11)
y = [8, 38, 22, 43, 10, 39, 54, 33, 52, 16]
plt.scatter(x, y, s=y)
# 显示
plt.show()
运行之后,效果如图2-50所示。
图2-50 气泡图
参数s表示点的大小,它的值可以是整数,也可以是列表。当取值为整数时,表示所有点的大小是一样的;当取值为列表时,会根据列表的值来定义每一个点的大小。
如果我们将s设置成与每个散点的数据大小一样,那么散点的大小就代表数据的大小,这样呈现出来的效果对应的就是气泡图。
其实上面这个例子的效果并不是很明显,我们可以让列表y中的所有元素同时放大5倍,然后将其赋值给参数s。请看下面的例子。
import matplotlib.pyplot as plt
# 绘图
x = range(1,11)
y = [8, 38, 22, 43, 10, 39, 54, 33, 52, 16]
# 将元素放大5倍
sizes = [item*5 for item in y]
plt.scatter(x, y, s=sizes)
# 显示
plt.show()
运行之后,效果如图2-51所示。
图2-51 放大气泡
import matplotlib.pyplot as plt
import random
# 生成随机颜色
def randomcolor():
colorArr = ['1','2','3','4','5','6','7','8','9','A','B','C','D','E','F']
color = ""
for i in range(6):
color += colorArr[random.randint(0,14)]
return "#"+color
# 生成随机颜色的列表
colors = []
for i in range(10):
colors.append(randomcolor())
# 绘图
x = range(1,11)
y = [8, 38, 22, 43, 10, 39, 54, 33, 52, 16]
sizes = [item*5 for item in y]
plt.scatter(x, y, s=sizes, color=colors)
# 显示
plt.show()
运行之后,效果如图2-52所示。
图2-52 气泡使用随机颜色
参数color和参数s一样,它的值除了可以是整数之外,还可以是列表。当它的值为列表时,表示为元素采用不同的颜色。
在Matplotlib中,我们可以使用bar()函数来绘制柱形图。柱形图也叫作“柱状图”,它的主要作用是展示数据的大小。
plt.bar(x, y, hatch)
参数x存放的是所有点的x轴坐标,参数y存放的是所有点的y轴坐标,它们可以是列表、数组、Series等。
参数hatch用于定义装饰线,常用的取值有/、|、-、\\。每一种符号字符串代表一种几何样式,并且符号字符串的符号数量越多,所对应的几何图形的密集程度就越高。
import matplotlib.pyplot as plt
# 绘图
x = [1, 2, 3, 4, 5]
y = [12, 25, 16, 23, 10]
plt.bar(x, y)
# 显示
plt.show()
运行之后,效果如图2-53所示。
图2-53 基本柱形图
import matplotlib.pyplot as plt
# 绘图
x = [1, 2, 3, 4, 5]
y = [12, 25, 16, 23, 10]
plt.bar(x, y, hatch="/")
# 显示
plt.show()
运行之后,效果如图2-54所示。
图2-54 hatch="/"效果
符号的数量越多,对应的几何图形的密集程度越高。当我们把hatch="/"改成hatch="//"之后,运行效果如图2-55所示。
图2-55 hatch="//"效果
当然,小伙伴们可以自行试一下hatch的其他取值,然后看看每一种取值的效果是怎样的。
在当前项目下的data文件夹中有一个gaokao.csv文件,项目结构如图2-56所示。gaokao.csv文件保存的是2011—2020年这10年每一年的高考人数(单位:万人)数据,内容如图2-57所示。
图2-56 项目结构
图2-57 gaokao.csv文件内容
import pandas as pd
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 读取数据
df = pd.read_csv(r"data/gaokao.csv")
# 绘制图表
plt.bar(df["年份"], df["人数"])
# 定义标题
plt.title("2011-2020年高考人数")
plt.xlabel("年份", loc="right")
plt.ylabel("人数(万人)", loc="top")
# 改变x轴刻度标签
plt.xticks(range(2011, 2021))
# 定义y轴刻度范围
plt.ylim(900, 1100)
# 添加注释文本
for a, b in zip(df["年份"], df["人数"]):
plt.text(a, b, b, ha="center", va="bottom")
# 显示
plt.show()
运行之后,效果如图2-58所示。
图2-58 案例运行效果
在实际开发中,柱形图的使用频率比较高。某些情况下,基本的柱形图并不能满足实际需求。所以我们还须掌握一些高级柱形图的绘制方法,高级柱形图主要包括以下2种。
● 堆叠柱形图。
● 并列柱形图。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = [1, 2, 3, 4, 5]
y1 = [3, 2, 4, 7, 1] # 男
y2 = [1, 5, 3, 8, 3] # 女
plt.bar(x, y1)
plt.bar(x, y2, bottom=y1)
# 定义标题
plt.title("婴儿出生人数(柱形图)")
plt.xlabel("日期")
plt.ylabel("人数")
# 显示
plt.show()
运行之后,效果如图2-59所示。
图2-59 堆叠柱形图
对于堆叠柱形图来说,多个数据的x轴坐标必须一致,y轴坐标可以不相同。另外就是绘制该柱形图需要借助bottom这个参数,应将放在该柱形图下面的数据的y轴坐标设置为bottom的值。
当然,我们不仅可以实现2种数据的堆叠,还可以对更多数据进行堆叠,小伙伴们可以自行尝试一下。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 绘图
x = [1, 2, 3, 4, 5]
y1 = [11, 13, 16, 10, 6]
y2 = [12, 17, 15, 12, 5]
width = 0.3
x1 = x
x2 = [i+width for i in x]
plt.bar(x1, y1, width=width, label="广州")
plt.bar(x2, y2, width=width, label="深圳")
plt.legend()
# 定义标题
plt.title("气温变化(柱形图)")
plt.xlabel("日期")
plt.ylabel("温度")
# 定义刻度标签
x = x2 = [i+width/2 for i in x]
dates = ["1日", "2日", "3日", "4日", "5日"]
plt.xticks(x, dates)
# 显示
plt.show()
运行之后,效果如图2-60所示。
图2-60 并列柱形图
绘制并列柱形图的重点是对width这个参数的灵活应用。关键代码是定义坐标轴刻度的代码。
条形图是一种和柱形图非常类似的图表,它们之间主要的区别就是柱形图是纵向的,而条形图是横向的。放在这里介绍,也是出于学习思路上的考虑。
在Matplotlib中,我们可以使用barh()函数来绘制一个条形图。其中,barh是“bar horizontal” (水平条形图)的缩写。
plt.barh(x, y, hatch)
barh()和bar()这两个函数的参数是完全一样的。其中,x和y用于定义坐标,hatch用于定义装饰线。
import matplotlib.pyplot as plt
# 绘图
x = [1, 2, 3, 4, 5]
y = [12, 25, 16, 23, 10]
plt.barh(x, y)
# 显示
plt.show()
运行之后,效果如图2-61所示。
图2-61 条形图
绘制条形图的barh()函数和绘制柱形图的bar()函数的其他用法也是一样的。对于条形图来说,它同样可以实现堆叠条形图、并列条形图,小伙伴们可以自行尝试一下。
在Matplotlib中,我们可以使用hist()函数来绘制直方图。直方图又叫作“质量分布图”,它的主要作用是展示数据的分布情况。hist是“histogram”(直方图)的缩写。
plt.hist(x, bins)
x是必选参数,它表示直方图的数据。bins是可选参数,用于定义如何分组。bins的常用取值有2种:整数、列表。
● 当取值为整数时,表示柱条有n(默认值为10)个。
● 当取值为列表时,表示定义每一个柱条的边界。
import matplotlib.pyplot as plt
# 绘图
x = [32, 12, 27, 56, 19, 16, 35, 52]
plt.hist(x)
# 显示
plt.show()
运行之后,效果如图2-62所示。
图2-62 不使用分组
直方图在本质上就是统计处于各个区间的数据的“个数”。如果没有设置第2个参数bins,那么Matplotlib就会自动分组。不过在大多数情况下,Matplotlib的自动分组是不符合我们预期的效果的,所以还是需要手动地使用bins来分组。
import matplotlib.pyplot as plt
# 绘图
x = [32, 12, 27, 56, 19, 16, 35, 52]
plt.hist(x, bins=5)
# 显示
plt.show()
运行之后,效果如图2-63所示。
图2-63 使用分组(整数)
plt.hist(x, bins=5)表示柱条的个数为5。需要注意的是,其中有一个区间没有数据,所以这里只显示4个柱条。
import matplotlib.pyplot as plt
# 绘图
x = [32, 12, 27, 56, 19, 16, 35, 52]
plt.hist(x, bins=[10, 20, 30, 40, 50, 60])
# 显示
plt.show()
运行之后,效果如图2-64所示。
图2-64 使用分组(列表)
plt.hist(x, bins)表示针对x传进来的数据,统计每一个分组中有多少个数据,那么它是怎么进行分组的呢?它是通过bins来进行分组的。
从图2-64可以很直观地看出,10~20分组中有3个数据,20~30分组中有1个数据,30~40分组中有2个数据,50~60分组中有2个数据。对于直方图,小伙伴们记住一句话就可以了:直方图用于统计每一个分组中数据的个数。
直方图和柱形图十分相似,我们来总结一下它们之间的区别,主要有以下3个方面。
● 柱形图用于展示数据的大小,而直方图用于展示数据的个数(频率)。
● 柱形图用于展示离散型数据的分布,而直方图用于展示连续型数据的分布。
● 柱形图的柱条之间有固定的间隙,而直方图的柱条之间是没有任何间隙的。
为了让直方图更加美观,hist()函数还提供了很多用于定义样式的参数,常用的如表2-13所示。
表2-13 hist()函数定义样式的参数
参数 |
说明 |
histtype |
直方图类型 |
rwidth |
柱条的宽度 |
facecolor |
柱条的颜色 |
edgecolor |
边框的颜色 |
alpha |
透明度 |
对于histtype这个参数来说,它常用的取值有bar(默认值)、barstacked、step、stepfilled。
import matplotlib.pyplot as plt
# 绘图
x = [32, 12, 27, 56, 19, 16, 35, 52]
plt.hist(x, bins=[10, 20, 30, 40, 50, 60], histtype="step")
# 显示
plt.show()
运行之后,效果如图2-65所示。
图2-65 改变直方图类型
import matplotlib.pyplot as plt
# 绘图
x = [32, 12, 27, 56, 19, 16, 35, 52]
plt.hist(x, bins=[10, 20, 30, 40, 50, 60], facecolor="#10A6CB", edgecolor="black")
# 显示
plt.show()
运行之后,效果如图2-66所示。
图2-66 改变颜色
在当前项目下的data文件夹中有一个age.csv文件,项目结构如图2-67所示。其中,age.csv文件保存的是100个乘客的年龄数据,部分内容如图2-68所示。
图2-67 项目结构
图2-68 age.csv文件的部分内容
import pandas as pd
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 读取数据
df = pd.read_csv(r"data/age.csv")
# 绘制图表
group = range(0, 100, 10)
plt.hist(df["年龄"], bins=group, facecolor="#10A6CB", edgecolor="black")
# 定义标题
plt.title("乘客年龄(直方图)")
plt.xlabel("年龄")
plt.ylabel("人数")
# 刻度标签
plt.xticks(range(0, 100, 10))
# 显示
plt.show()
运行之后,效果如图2-69所示。
图2-69 案例运行效果
直方图和柱形图很相似,但是它们之间其实是有着本质上的区别的:柱形图用于展示数据的大小,而直方图用于统计数据的个数。
import numpy as np
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 随机生成1000个符合正态分布的数据
x = np.random.randn(1000)
plt.hist(x, bins=40, color="#10A6CB", edgecolor="black")
# 定义标题
plt.title("正态分布直方图")
plt.xlabel("区间")
plt.ylabel("频率")
# 显示
plt.show()
运行之后,效果如图2-70所示。
图2-70 正态分布直方图
np.random.randn(1000)用于随机生成1000个符合正态分布的数据,这是属于数据分析中NumPy的内容,小伙伴们可自行查阅了解。
在Matplotlib中,我们可以使用pie()函数来绘制饼状图。饼状图也叫作“饼图”。饼状图有些特殊,它是没有坐标的,因为它的作用是展示各个部分占总和的比例。
plt.pie(x)
x是必选参数,它用于定义饼状图的数据部分。
import matplotlib.pyplot as plt
# 绘图
x= [8, 4, 6, 10] # 各部分的值
plt.pie(x) # 绘制饼状图
# 显示
plt.show()
运行之后,效果如图2-71所示。
图2-71 饼状图
为了让饼状图更加美观,pie()函数还提供了很多用于定义样式的参数,常用的如表2-14所示。
表2-14 pie()函数定义样式的参数
参数 |
说明 |
labels |
各部分的标题(列表) |
colors |
各部分的颜色(列表) |
autopct |
显示百分比 |
explode |
是否拉出某部分(元组) |
shadow |
是否显示阴影(元组) |
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 各部分的数据(单位:亿美元)
x = [8.9, 4.1, 12.1, 8.5, 11.5]
# 各部分的标题
movies = ["蜘蛛侠", "蝙蝠侠", "钢铁侠", "毒液", "海王"]
# 绘制饼状图
plt.pie(x,
labels = movies,
autopct = "%1.1f%%"
)
plt.title("电影票房占比")
# 显示
plt.show()
运行之后,效果如图2-72所示。
图2-72 添加标题和百分比
参数autopct表示百分比的格式,语法为"%格式%%"。比如"%1.1f%%"表示整数占1位,小数占1位。而"%2.1f%%"表示整数占2位,小数占1位。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 各部分的数据(单位:亿美元)
x = [8.9, 4.1, 12.1, 8.5, 11.5]
# 各部分的标题
movies = ["蜘蛛侠", "蝙蝠侠", "钢铁侠", "毒液", "海王"]
# 绘制饼状图
plt.pie(x,
labels = movies,
autopct = "%1.1f%%",
colors=["lightskyblue", "orangered", "purple", "hotpink", "yellow"]
)
plt.title("电影票房占比")
# 显示
plt.show()
运行之后,效果如图2-73所示。
图2-73 自定义颜色
如果觉得饼状图默认的颜色不够美观,那么可以使用colors这个参数来定义每一个扇形的颜色。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 各部分的数据(单位:亿美元)
x = [8.9, 4.1, 12.1, 8.5, 11.5]
# 各部分的标题
movies = ["蜘蛛侠", "蝙蝠侠", "钢铁侠", "毒液", "海王"]
# 绘制饼状图
plt.pie(x,
labels = movies,
autopct = "%1.1f%%",
explode = (0.1, 0, 0, 0, 0)
)
plt.title("电影票房占比")
# 显示
plt.show()
运行之后,效果如图2-74所示。
图2-74 “拉出”一部分
explode=(0.1, 0, 0, 0, 0)表示将第1部分“拉出来”。如果想要将第2部分拉出来,可以这样来写:explode=(0, 0.1, 0, 0, 0),效果如图2-75所示。
图2-75 拉出第2部分
如果想要改变拉出的距离,只需要改变小数部分的数值就可以了。比如将explode=(0.1, 0, 0, 0, 0)改为explode=(0.5, 0, 0, 0, 0),效果如图2-76所示。
图2-76 拉出更大距离
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 各部分的数据(单位:亿美元)
x = [8.9, 4.1, 12.1, 8.5, 11.5]
# 各部分的标题
movies = ["蜘蛛侠", "蝙蝠侠", "钢铁侠", "毒液", "海王"]
# 绘制饼状图
plt.pie(x,
labels = movies,
autopct = "%1.1f%%",
explode = (0.1, 0, 0, 0, 0),
shadow=True
)
plt.title("电影票房占比")
# 显示
plt.show()
运行之后,效果如图2-77所示。
图2-77 添加阴影效果
最后要说明一下,虽然饼状图的展示效果不错,但它仅适用于少量数据的呈现。大量数据就不适合使用饼状图。因为如果将饼状图分块太多,那么占比太小的数据就会看不清楚。
圆环图也叫作“环形图”,因为与饼状图类似,所以放在这里介绍。在Matplotlib中,我们可以配合使用pie()函数的radius和wedgeprops这2个参数来实现圆环图。
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 各部分的数据(单位:亿美元)
x = [8.9, 4.1, 12.1, 8.5, 11.5]
# 各部分的标题
movies = ["蜘蛛侠", "蝙蝠侠", "钢铁侠", "毒液", "海王"]
# 绘制圆环图
plt.pie(x,
labels = movies,
autopct = "%1.1f%%",
radius=1.0,
wedgeprops={"width": 0.6}
)
plt.title("电影票房占比")
# 显示
plt.show()
运行之后,效果如图2-78所示。
图2-78 圆环图
radius=1.0用于定义外圆半径,其值为默认的100%。wedgeprops={"width":0.6}用于定义内圆半径,其值为默认的60%。
箱线图也叫作“箱形图”。箱线图使用6个统计量来描述数据,也就是最大值、上四分位数、中位数、下四分位数、最小值、异常值,如图2-79所示。
图2-79 箱线图
在Matplotlib中,我们可以使用boxplot()函数来绘制箱线图。箱线图的主要作用有2个:① 查看数据的分布情况;② 发现数据中的异常值。
plt.boxplot(x)
x表示箱线图中的数据。它可以是一维数据(如一维列表或Series),也可以是二维数据(如二维列表或DataFrame)。如果是一维数据,则表示绘制一个箱子;如果是二维数据,则表示绘制多个箱子。
import matplotlib.pyplot as plt
# 绘图
x = [0, 8, 1, 3, 6]
plt.boxplot(x)
# 显示
plt.show()
运行之后,效果如图2-80所示。
图2-80 有一个箱子的箱线图
从图2-80可以看出,对于x这一组数据,它的最大值是8、上四分位数是6、中位数是3、下四分位数是1、最小值是0。其中四分位数以及中位数都是数据分析中的概念。
import matplotlib.pyplot as plt
# 绘图
x1 = [0, 8, 1, 3, 6]
x2 = [16, 13, 10, 14, 12]
x3 = [20, 24, 21, 23, 27]
plt.boxplot([x1, x2, x3])
# 显示
plt.show()
运行之后,效果如图2-81所示。
图2-81 有多个箱子的箱线图
同时绘制多个箱子也很简单,使boxplot()函数接收一个列表作为参数就可以了。列表的每一个元素本身又是一个列表。
import matplotlib.pyplot as plt
# 绘图
x = [23, 34, 11, 29, 33, 13, 33, 45, 80, 90]
plt.boxplot(x)
# 显示
plt.show()
运行之后,效果如图2-82所示。
图2-82 异常值
x中的数据大多数分布在10~50范围内,但是这里的80和90已经远远超出这个范围,所以Matplotlib会自动标识它们为异常值(异常数据)。图2-82中的两个小圆圈代表的就是异常值。
需要清楚的是,异常值是绘制箱线图时自动识别出的,而不是我们手动设置的。一般来说,如果某些数据不在大多数数据所在的范围,就会自动被标识为异常值。
为了让箱线图更加美观,boxplot()函数还提供了很多用于定义样式的参数,常用的如表2-15所示。
表2-15 boxplot()函数定义样式的参数
参数 |
说明 |
notch |
是否有缺口,默认值为False(不带缺口) |
vert |
是否为纵向,默认值为True(纵向) |
showmeans |
是否显示平均值,默认值为False(不显示) |
showfliers |
是否显示异常值,默认值为True(显示) |
flierprops |
异常点的样式,值是字典 |
boxprops |
箱子的样式,值是字典,需要结合patch_artist=True一起使用 |
labels |
指定每个箱子的标签 |
import matplotlib.pyplot as plt
# 绘图
x = [23, 34, 11, 29, 33, 13, 33, 45, 80, 90]
plt.boxplot(x, notch=True)
# 显示
plt.show()
运行之后,效果如图2-83所示。
图2-83 带缺口的箱线图
notch=True用于设置带缺口的箱线图。缺口的作用其实非常简单,就是突出中位数。
import matplotlib.pyplot as plt
# 绘图
x = [23, 34, 11, 29, 33, 13, 33, 45, 80, 90]
plt.boxplot(x, vert=False)
# 显示
plt.show()
运行之后,效果如图2-84所示。
图2-84 横向的箱线图
import matplotlib.pyplot as plt
# 绘图
x = [23, 34, 11, 29, 33, 13, 33, 45, 80, 90]
plt.boxplot(x, showmeans=True)
# 显示
plt.show()
运行之后,效果如图2-85所示。
图2-85 显示平均值
平均值和中位数是两个完全不一样的概念,小伙伴们一定要严格区分,别把它们搞混淆了。
import matplotlib.pyplot as plt
# 绘图
x = [23, 34, 11, 29, 33, 13, 33, 45, 80, 90]
plt.boxplot(x, showfliers=False)
# 显示
plt.show()
运行之后,效果如图2-86所示。
图2-86 隐藏异常值
对于这个例子来说,它存在2个异常值:80和90。showfliers=False用于隐藏异常值。
import matplotlib.pyplot as plt
# 绘图
x = [23, 34, 11, 29, 33, 13, 33, 45, 80, 90]
styles = {
"marker": "D",
"markersize": 8,
"markerfacecolor": "orange",
"markeredgecolor": "red"
}
plt.boxplot(x, flierprops=styles)
# 显示
plt.show()
运行之后,效果如图2-87所示。
图2-87 定义异常点的样式
异常点的样式可以通过marker、markersize、markerfacecolor、markeredgecolor这4个参数来定义,说明如表2-16所示。
表2-16 定义异常点样式的参数
参数 |
说明 |
marker |
外观 |
markersize |
大小 |
markerfacecolor |
异常点颜色 |
markeredgecolor |
边框颜色 |
import matplotlib.pyplot as plt
# 绘图
x = [23, 34, 11, 29, 33, 13, 33, 45, 80, 90]
styles = {
"facecolor": "pink",
"edgecolor": "red",
}
plt.boxplot(x, patch_artist=True, boxprops=styles)
# 显示
plt.show()
运行之后,效果如图2-88所示。
图2-88 定义箱子的样式
想要使boxprops的设置生效,我们必须先设置patch_artist=True。boxprops和patch_artist这2个参数是配合使用的。此外,facecolor用于定义箱子颜色,而edgecolor用于定义边框颜色。
import matplotlib.pyplot as plt
# 绘图
x1 = [0, 8, 1, 3, 6]
x2 = [16, 13, 10, 14, 12]
x3 = [20, 24, 21, 23, 27]
plt.boxplot([x1, x2, x3], labels=["A", "B", "C"])
# 显示
plt.show()
运行之后,效果如图2-89所示。
图2-89 添加标签说明
当同时绘制多个箱子时,我们可以使用labels参数来给每一个箱子定义标签说明。从上文可以看出,箱线图的绘制其实非常简单,大家不要因为之前没有接触过,就被它“可怕的外表”给欺骗了。
最后需要说明的是,箱线图和散点图有些类似,它们非常适用于快速找出数据中的异常值,这对于我们进行数据分析是非常有用的。
在当前项目下的data文件夹中有一个staff.csv文件,项目结构如图2-90所示。其中staff.csv文件保存的是所有员工的年龄数据,内容如图2-91所示。接下来我们尝试使用箱线图来判断年龄数据是否存在异常值。
图2-90 项目结构
图2-91 staff.csv文件内容
import pandas as pd
import matplotlib.pyplot as plt
# 设置
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 读取数据
df = pd.read_csv(r"data/staff.csv")
# 绘制图表
styles = {
"markerfacecolor": "red",
"markeredgecolor": "red"
}
plt.boxplot(df["年龄"], flierprops=styles)
plt.title("员工年龄箱线图")
# 显示
plt.show()
运行之后,效果如图2-92所示。
图2-92 案例运行效果
从图2-92可以看出,数据中存在2个异常值。那么是不是箱线图就一定能判断出异常值呢?那可不一定。比如我们修改一下staff.csv的数据,也就是将小明的年龄数据修改成142,如图2-93所示。再次运行代码,此时效果如图2-94所示。
图2-93 修改后的staff.csv
图2-94 修改staff.csv后的运行效果
为什么这个时候箱线图就没能把异常值给找出来呢?这是因为对于staff.csv这个数据集文件来说,它的异常值所占的比例比较大,此时箱线图会把这些异常值当作正常值。当然,当样本数量足够多时,箱线图还是可以非常准确地判断出异常值的。
从上例我们也应该知道,箱线图只是一种辅助工具,并不能保证一定能判断出异常值。所以在实际工作中,我们除了借助可视化库之外,也要结合自己的工作经验,这样才能更加准确地判断数据。
微信扫码关注【异步社区】微信公众号,回复“e58713”获取本书配套资源以及异步社区15天VIP会员卡,近千本电子书免费畅读。