《利用Python进行数据分析·第2版》第9章(中) 绘图和可视化
作者:SeanCheney Python爱好者社区专栏作者
简书专栏:https://www.jianshu.com/u/130f76596b02
前文传送门:
【翻译】《利用Python进行数据分析·第2版》第1章 准备工作
【翻译】《利用Python进行数据分析·第2版》第2章(上)Python语法基础,IPython和Jupyter
【翻译】《利用Python进行数据分析·第2版》第2章(中)Python语法基础,IPython和Jupyter
【翻译】《利用Python进行数据分析·第2版》第2章(下)Python语法基础,IPython和Jupyter
【翻译】《利用Python进行数据分析·第2版》第3章(上)Python的数据结构、函数和文件
【翻译】《利用Python进行数据分析·第2版》第3章(中)Python的数据结构、函数和文件
【翻译】《利用Python进行数据分析·第2版》第3章(下)Python的数据结构、函数和文件
【翻译】《利用Python进行数据分析·第2版》第4章(上)NumPy基础:数组和矢量计算
【翻译】《利用Python进行数据分析·第2版》第4章(中)NumPy基础:数组和矢量计算
【翻译】《利用Python进行数据分析·第2版》第4章(下)NumPy基础:数组和矢量计算
【翻译】《利用Python进行数据分析·第2版》第5章(上)pandas入门
【翻译】《利用Python进行数据分析·第2版》第5章(中)pandas入门
【翻译】《利用Python进行数据分析·第2版》第5章(下)pandas入门
【翻译】《利用Python进行数据分析·第2版》第6章(上) 数据加载、存储与文件格式
【翻译】《利用Python进行数据分析·第2版》第6章(中) 数据加载、存储与文件格式
【翻译】《利用Python进行数据分析·第2版》第6章(下) 数据加载、存储与文件格式
【翻译】《利用Python进行数据分析·第2版》第7章(上)数据清洗和准备
【翻译】《利用Python进行数据分析·第2版》第7章(中) 数据清洗和准备
【翻译】《利用Python进行数据分析·第2版》第7章(下) 数据清洗和准备
【翻译】《利用Python进行数据分析·第2版》第8章(上) 数据规整:聚合、合并和重塑
【翻译】《利用Python进行数据分析·第2版》第8章(中) 数据规整:聚合、合并和重塑
【翻译】《利用Python进行数据分析·第2版》第8章(下) 数据规整:聚合、合并和重塑
【翻译】《利用Python进行数据分析·第2版》第9章(上) 绘图和可视化
刻度、标签和图例
对于大多数的图表装饰项,其主要实现方式有二:使用过程型的pyplot接口(例如,matplotlib.pyplot)以及更为面向对象的原生matplotlib API。
pyplot接口的设计目的就是交互式使用,含有诸如xlim、xticks和xticklabels之类的方法。它们分别控制图表的范围、刻度位置、刻度标签等。其使用方式有以下两种:
调用时不带参数,则返回当前的参数值(例如,plt.xlim()返回当前的X轴绘图范围)。
调用时带参数,则设置参数值(例如,plt.xlim([0,10])会将X轴的范围设置为0到10)。
所有这些方法都是对当前或最近创建的AxesSubplot起作用的。它们各自对应subplot对象上的两个方法,以xlim为例,就是ax.get_xlim和ax.set_xlim。我更喜欢使用subplot的实例方法(因为我喜欢明确的事情,而且在处理多个subplot时这样也更清楚一些)。当然你完全可以选择自己觉得方便的那个。
设置标题、轴标签、刻度以及刻度标签
为了说明自定义轴,我将创建一个简单的图像并绘制一段随机漫步(如图9-8所示):
In [37]: fig = plt.figure() In [38]: ax = fig.add_subplot(1, 1, 1) In [39]: ax.plot(np.random.randn(1000).cumsum())
图9-8 用于演示xticks的简单线型图(带有标签)
要改变x轴刻度,最简单的办法是使用set_xticks和set_xticklabels。前者告诉matplotlib要将刻度放在数据范围中的哪些位置,默认情况下,这些位置也就是刻度标签。但我们可以通过set_xticklabels将任何其他的值用作标签:
In [40]: ticks = ax.set_xticks([0, 250, 500, 750, 1000]) In [41]: labels = ax.set_xticklabels(['one', 'two', 'three', 'four', 'five'], ....: rotation=30, fontsize='small')
rotation选项设定x刻度标签倾斜30度。最后,再用set_xlabel为X轴设置一个名称,并用set_title设置一个标题(见图9-9的结果):
In [42]: ax.set_title('My first matplotlib plot') Out[42]: <matplotlib.text.Text at 0x7fb624d055f8> In [43]: ax.set_xlabel('Stages')
图9-9 用于演示xticks的简单线型图
Y轴的修改方式与此类似,只需将上述代码中的x替换为y即可。轴的类有集合方法,可以批量设定绘图选项。前面的例子,也可以写为:
props = { 'title': 'My first matplotlib plot', 'xlabel': 'Stages' } ax.set(**props)
添加图例
图例(legend)是另一种用于标识图表元素的重要工具。添加图例的方式有多种。最简单的是在添加subplot的时候传入label参数:
In [44]: from numpy.random import randn In [45]: fig = plt.figure(); ax = fig.add_subplot(1, 1, 1) In [46]: ax.plot(randn(1000).cumsum(), 'k', label='one') Out[46]: [<matplotlib.lines.Line2D at 0x7fb624bdf860>] In [47]: ax.plot(randn(1000).cumsum(), 'k--', label='two') Out[47]: [<matplotlib.lines.Line2D at 0x7fb624be90f0>] In [48]: ax.plot(randn(1000).cumsum(), 'k.', label='three') Out[48]: [<matplotlib.lines.Line2D at 0x7fb624be9160>]
在此之后,你可以调用ax.legend()或plt.legend()来自动创建图例(结果见图9-10):
In [49]: ax.legend(loc='best')
图9-10 带有三条线以及图例的简单线型图
legend方法有几个其它的loc位置参数选项。请查看文档字符串(使用ax.legend?)。
loc告诉matplotlib要将图例放在哪。如果你不是吹毛求疵的话,"best"是不错的选择,因为它会选择最不碍事的位置。要从图例中去除一个或多个元素,不传入label或传入label='nolegend'即可。(中文第一版这里把best错写成了beat)
注解以及在Subplot上绘图
除标准的绘图类型,你可能还希望绘制一些子集的注解,可能是文本、箭头或其他图形等。注解和文字可以通过text、arrow和annotate函数进行添加。text可以将文本绘制在图表的指定坐标(x,y),还可以加上一些自定义格式:
ax.text(x, y, 'Hello world!', family='monospace', fontsize=10)
注解中可以既含有文本也含有箭头。例如,我们根据最近的标准普尔500指数价格(来自Yahoo!Finance)绘制一张曲线图,并标出2008年到2009年金融危机期间的一些重要日期。你可以在Jupyter notebook的一个小窗中试验这段代码(图9-11是结果):
from datetime import datetime fig = plt.figure() ax = fig.add_subplot(1, 1, 1) data = pd.read_csv('examples/spx.csv', index_col=0, parse_dates=True) spx = data['SPX'] spx.plot(ax=ax, style='') crisis_data = [ (datetime(2007, 10, 11), 'Peak of bull market'), (datetime(2008, 3, 12), 'Bear Stearns Fails'), (datetime(2008, 9, 15), 'Lehman Bankruptcy') ] for date, label in crisis_data: ax.annotate(label, xy=(date, spx.asof(date) + 75), xytext=(date, spx.asof(date) + 225), arrowprops=dict(facecolor='black', headwidth=4, width=2, headlength=4), horizontalalignment='left', verticalalignment='top') # Zoom in on 2007-2010 ax.set_xlim(['1/1/2007', '1/1/2011']) ax.set_ylim([600, 1800]) ax.set_title('Important dates in the 2008-2009 financial crisis')
图9-11 2008-2009年金融危机期间的重要日期
这张图中有几个重要的点要强调:ax.annotate方法可以在指定的x和y坐标轴绘制标签。我们使用set_xlim和set_ylim人工设定起始和结束边界,而不使用matplotlib的默认方法。最后,用ax.set_title添加图标标题。
更多有关注解的示例,请访问matplotlib的在线示例库。
图形的绘制要麻烦一些。matplotlib有一些表示常见图形的对象。这些对象被称为块(patch)。其中有些(如Rectangle和Circle),可以在matplotlib.pyplot中找到,但完整集合位于matplotlib.patches。
要在图表中添加一个图形,你需要创建一个块对象shp,然后通过ax.add_patch(shp)将其添加到subplot中(如图9-12所示):
fig = plt.figure() ax = fig.add_subplot(1, 1, 1) rect = plt.Rectangle((0.2, 0.75), 0.4, 0.15, color='k', alpha=0.3) circ = plt.Circle((0.7, 0.2), 0.15, color='b', alpha=0.3) pgon = plt.Polygon([[0.15, 0.15], [0.35, 0.4], [0.2, 0.6]], color='g', alpha=0.5) ax.add_patch(rect) ax.add_patch(circ) ax.add_patch(pgon)
图9-12 由三个块图形组成的图
如果查看许多常见图表对象的具体实现代码,你就会发现它们其实就是由块patch组装而成的。
将图表保存到文件
利用plt.savefig可以将当前图表保存到文件。该方法相当于Figure对象的实例方法savefig。例如,要将图表保存为SVG文件,你只需输入:
plt.savefig('figpath.svg')
文件类型是通过文件扩展名推断出来的。因此,如果你使用的是.pdf,就会得到一个PDF文件。我在发布图片时最常用到两个重要的选项是dpi(控制“每英寸点数”分辨率)和bbox_inches(可以剪除当前图表周围的空白部分)。要得到一张带有最小白边且分辨率为400DPI的PNG图片,你可以:
plt.savefig('figpath.png', dpi=400, bbox_inches='tight')
savefig并非一定要写入磁盘,也可以写入任何文件型的对象,比如BytesIO:
from io import BytesIO buffer = BytesIO() plt.savefig(buffer) plot_data = buffer.getvalue()
表9-2列出了savefig的其它选项。
表9-2 Figure.savefig的选项
matplotlib配置
matplotlib自带一些配色方案,以及为生成出版质量的图片而设定的默认配置信息。幸运的是,几乎所有默认行为都能通过一组全局参数进行自定义,它们可以管理图像大小、subplot边距、配色方案、字体大小、网格类型等。一种Python编程方式配置系统的方法是使用rc方法。例如,要将全局的图像默认大小设置为10×10,你可以执行:
表9-2列出了savefig的其它选项。
表9-2 Figure.savefig的选项
matplotlib配置
matplotlib自带一些配色方案,以及为生成出版质量的图片而设定的默认配置信息。幸运的是,几乎所有默认行为都能通过一组全局参数进行自定义,它们可以管理图像大小、subplot边距、配色方案、字体大小、网格类型等。一种Python编程方式配置系统的方法是使用rc方法。例如,要将全局的图像默认大小设置为10×10,你可以执行:
plt.rc('figure', figsize=(10, 10))
rc的第一个参数是希望自定义的对象,如'figure'、'axes'、'xtick'、'ytick'、'grid'、'legend'等。其后可以跟上一系列的关键字参数。一个简单的办法是将这些选项写成一个字典:
font_options = {'family' : 'monospace', 'weight' : 'bold', 'size' : 'small'} plt.rc('font', **font_options)
要了解全部的自定义选项,请查阅matplotlib的配置文件matplotlibrc(位于matplotlib/mpl-data目录中)。如果对该文件进行了自定义,并将其放在你自己的.matplotlibrc目录中,则每次使用matplotlib时就会加载该文件。
下一节,我们会看到,seaborn包有若干内置的绘图主题或类型,它们使用了matplotlib的内部配置。
9.2 使用pandas和seaborn绘图
matplotlib实际上是一种比较低级的工具。要绘制一张图表,你组装一些基本组件就行:数据展示(即图表类型:线型图、柱状图、盒形图、散布图、等值线图等)、图例、标题、刻度标签以及其他注解型信息。
在pandas中,我们有多列数据,还有行和列标签。pandas自身就有内置的方法,用于简化从DataFrame和Series绘制图形。另一个库seaborn(https://seaborn.pydata.org/),由Michael Waskom创建的静态图形库。Seaborn简化了许多常见可视类型的创建。
提示:引入seaborn会修改matplotlib默认的颜色方案和绘图类型,以提高可读性和美观度。即使你不使用seaborn API,你可能也会引入seaborn,作为提高美观度和绘制常见matplotlib图形的简化方法。
线型图
Series和DataFrame都有一个用于生成各类图表的plot方法。默认情况下,它们所生成的是线型图(如图9-13所示):
In [60]: s = pd.Series(np.random.randn(10).cumsum(), index=np.arange(0, 100, 10)) In [61]: s.plot()
图9-13 简单的Series图表示例
该Series对象的索引会被传给matplotlib,并用以绘制X轴。可以通过use_index=False禁用该功能。X轴的刻度和界限可以通过xticks和xlim选项进行调节,Y轴就用yticks和ylim。plot参数的完整列表请参见表9-3。我只会讲解其中几个,剩下的就留给读者自己去研究了。
表9-3 Series.plot方法的参数
pandas的大部分绘图方法都有一个可选的ax参数,它可以是一个matplotlib的subplot对象。这使你能够在网格布局中更为灵活地处理subplot的位置。
DataFrame的plot方法会在一个subplot中为各列绘制一条线,并自动创建图例(如图9-14所示):
In [62]: df = pd.DataFrame(np.random.randn(10, 4).cumsum(0), ....: columns=['A', 'B', 'C', 'D'], ....: index=np.arange(0, 100, 10)) In [63]: df.plot()
图9-14 简单的DataFrame绘图
plot属性包含一批不同绘图类型的方法。例如,df.plot()等价于df.plot.line()。后面会学习这些方法。
笔记:plot的其他关键字参数会被传给相应的matplotlib绘图函数,所以要更深入地自定义图表,就必须学习更多有关matplotlib API的知识。
DataFrame还有一些用于对列进行灵活处理的选项,例如,是要将所有列都绘制到一个subplot中还是创建各自的subplot。详细信息请参见表9-4。
表9-4 专用于DataFrame的plot参数
注意: 有关时间序列的绘图,请见第11章。
柱状图
plot.bar()和plot.barh()分别绘制水平和垂直的柱状图。这时,Series和DataFrame的索引将会被用作X(bar)或Y(barh)刻度(如图9-15所示):
In [64]: fig, axes = plt.subplots(2, 1) In [65]: data = pd.Series(np.random.rand(16), index=list('abcdefghijklmnop')) In [66]: data.plot.bar(ax=axes[0], color='k', alpha=0.7) Out[66]: <matplotlib.axes._subplots.AxesSubplot at 0x7fb62493d470> In [67]: data.plot.barh(ax=axes[1], color='k', alpha=0.7)
图9-15 水平和垂直的柱状图
color='k'和alpha=0.7设定了图形的颜色为黑色,并使用部分的填充透明度。
赞赏作者
Python爱好者社区历史文章大合集:
Python爱好者社区历史文章列表(每周append更新一次)
关注后在公众号内回复“课程”即可获取:
小编的Python入门视频课程!!!
崔老师爬虫实战案例免费学习视频。
丘老师数据科学入门指导免费学习视频。
陈老师数据分析报告制作免费学习视频。
玩转大数据分析!Spark2.X+Python 精华实战课程免费学习视频。
丘老师Python网络爬虫实战免费学习视频。