利用Python进行数据分析——绘图和可视化(八)(2)

1、注释以及在Subplot上绘图 除标准的图表对象之外,你可能还希望绘制一些自定义的注释(比如文本、箭头或其他图形等)。 注释可以通过text、arrow和annotate等函数进行添加。text可以将文本绘制在图表的指定坐标(x, y),还可以加上一些自定义格式:

In [41]: ax.text(x, y, ‘Hello world!‘, family=‘monospace‘, fontsize=10)

注解中可以既含有文本也含有箭头。例如,我们根据2007年以来的标准普尔500指数收盘价格(来自Yahoo! Finance)绘制一张曲线图,并标出2008年到2009年金融危机期间的一些重要日期。如下所示:

更多干货分享加python编程语言学习QQ群 515267276

bubuko.com,布布扣

from datetime import datetime fig = plt.figure() ax = fig.add_subplot(1, 1, 1) data = pd.read_csv(‘ch08/spx.csv‘, index_col=0, parse_dates=True) spx = data[‘SPX‘] spx.plot(ax=ax, style=‘k-‘) 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) + 50), xytext=(date, spx.asof(date) + 200), arrowprops=dict(facecolor=‘black‘), 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 2008-2009 financial crisis‘)

图像的绘制要麻烦一些。matplotlib有一些表示常见图形的对象。这些对象被称为块(patch)。其中有些可以在matplotlib.pyplot中找到(如Rectangle和Circle),但完整集合位于matplotlib.patches。

要在图表中添加一个图形,你需要创建一个块对象shp,然后通过ax.add_patch(shp)将其添加到subplot中。

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)

bubuko.com,布布扣

说明:

扫描二维码关注公众号,回复: 4207864 查看本文章

如果查看许多常见图表对象的具体实现代码,你就会发现它们其实就是由块组装而成的。

2、将图表保存到文件

利用plt.savefig可以将当前图表保存到文件。该方法相当于Figure对象的实例方法savefig。例如,要将图表保存为SVG文件,你只需输入:

In [42]: plt.savefig(‘figpath.svg‘)

文件类型是通过文件扩展名推断出来的。因此,如果你使用的是.gif,就会得到一个PDF文件。我在发布图片时最常用到两个重要的选项是dpi(控制“每英寸点数”分辨率)和bbox_inches(可以翦除当前图表周围的空白部分)。要得到一张带有最小白边且分辨率为400DPI的PNG图片,你只需输入:

In [43]: plt.savefig(‘figpath.svg‘, dpi=400, bbox_inches=‘tight‘)

savefig并非一定要写入磁盘,也可以写入任何文件型的对象,比如StringIO:

In [44]: from io import StringIO In [45]: buffer = StringIO() In [46]: plt.savefig(buffer) In [47]: plot_data = buffer.getvalue()

这对在Web上提供动态生成的图片是很实用的。Figure.savefig方法的参数及说明如下所示:
bubuko.com,布布扣

3、matplotlib配置

matplotlib自带一些配色方案,以及为生成出版质量的图片而设定的默认配置信息。幸运的是,几乎所有默认行为都能通过一组全局参数进行自定义,它们可以管理图像大小、subplot边距、配色方案、字体大小、网格类型等。操作matplotlib配置系统的方式主要有两种。第一种是Python编程方式,即利用rc方法。比如说,要将全局的图像默认大小设置为10bubuko.com,布布扣10,你可以执行:

In [45]: plt.rc(‘figure‘, figsize=(10, 10))

rc的第一个参数是希望自定义的对象,如‘figure’、‘axes’、‘xtick’、‘ytick’、‘grid’、‘legend’等。其后可以跟上一系列的关键字参数。最简单的办法是将这些选项写成一个字典:

In [46]: font_options = {‘family‘ : ‘monospace‘, ‘weight‘ : ‘bold‘, ‘size‘ : ‘small‘} In [47]: plt.rc(‘font‘, **font_options)

要了解全部的自定义选项,请查阅matplotlib的配置文件matplotlibrc(位于matplotlib/mpl-data目录中)。如果对该文件进行了自定义,并将其放在你自己的.matplotlib目录中,则每次使用matplotlib时就会加载该文件。

更多干货分享加python编程语言学习QQ群 515267276

4、pandas中的绘图函数

不难看出,matplotlib实际上是一种比较低级的工具。要组装一张图表,你得用它的各种基础组件才行:数据显示(即图表类型:线型图、柱状图、盒形图、散布图、等值线图等)、图例、标题、刻度标签以及其他注解型信息。这是因为要根据数据制作一张完整图表通常都需要用到多个对象。在pandas中,我们有行标签、列标签以及分组信息(可能有)。这也就是说,要制作一张完整的图表,原本需要一大堆的matplotlib代码,现在只需要一两条简洁的语句就可以了。pandas有许多能够利用DataFrame对象数组组织特点来创建标准图表的高级绘图方法(这些函数的数量还在不断增加)。

5、线型图

Series和DataFrame都有一个用于生成各类图表的plot方法。默认情况下,它们所生成的是线型图:

In [47]: import pandas as pd In [48]: s = pd.Series(np.random.randn(10).cumsum(), index=np.arange(0, 100, 10)) In [49]: s.plot() Out[49]:

bubuko.com,布布扣
该Series对象的索引会被传给matplotlib,并用以绘制X轴。可以通过use_index=False禁用该功能。X轴的刻度和界限可以通过xticks和xlim选项进行调节,Y轴就用yticks和ylim。plot参数的完整列表如下所示:

bubuko.com,布布扣

bubuko.com,布布扣

pandas的大部分绘图方法都有一个可选的ax参数,它可以是一个matplotlib的subplot对象。这使你能够在网格布局中更为灵活地处理subplot的位置。

DataFrame的plot方法会在一个subplot中为各列绘制一条线,并自动创建图例,如下所示:

bubuko.com,布布扣

注意:

plot的其他关键字参数会被传给相应的matplotlib绘图函数,所以要更深入地自定义图表,就必须学习更多有关matplotlib API的知识。

DataFrame还有一些用于对列进行灵活处理的选项,例如,是要将所有列都绘制到一个subplot中还是创建各自的subplot,详细信息如下所示:

bubuko.com,布布扣

bubuko.com,布布扣

6、柱状图

在生成线型图的代码中加上kind=‘bar‘(垂直柱状图)或kind=‘barh‘(水平柱状图)即可生成柱状图。这时,Series和DataFrame的索引将会被用作X(bar)或Y(barh)刻度,如下所示:

更多干货分享加python编程语言学习QQ群 515267276

In [55]: fig, axes = plt.subplots(2, 1) In [56]: data = pd.Series(np.random.rand(16), index=list(‘abcdefghijklmnop‘)) In [57]: data.plot(kind=‘bar‘, ax=axes[0], color=‘k‘, alpha=0.7) Out[57]: In [58]: data.plot(kind=‘barh‘, ax=axes[1], color=‘k‘, alpha=0.7) Out[58]:

bubuko.com,布布扣
对于DataFrame,柱状图会将每一行的值分为一组,如下所示:

In [60]: df = pd.DataFrame(np.random.rand(6, 4), index=[‘one‘, ‘two‘, ‘three‘, ‘four‘, ‘five‘, ‘six‘], columns=pd.Index([‘A‘, ‘B‘, ‘C‘, ‘D‘], name=‘Genus‘)) In [61]: df.plot(kind=‘bar‘) Out[61]:

bubuko.com,布布扣
 

DataFrame各列的名称“Genus”被用作了图例的标题。设置stacked=True即可为DataFrame生成堆积柱状图,这样每行的值就会被堆积在一起,如下所示:

In [62]: df.plot(kind=‘bar‘, stacked=True, alpla=0.5)

注意:
柱状图有一个非常不错的用法:利用value_counts图形化显示Series中各值的出现频率,比如s.value_counts().plot(kind=‘bar‘)。
以小费数据集为例,假设我们想要做一张堆积柱状图以展示每天各种聚会规模的数据点的百分比。我用read_csv将数据加载进来,然后根据日期和聚会规模创建一张交叉表:

小费数据集:http://download.csdn.net/detail/shengshengwang/7197845

In [63]: tips = pd.read_csv(‘ch08/tips.csv‘) In [64]: party_counts = pd.crosstab(tips.day, tips.size) In [65]: party_counts Out[65]: size 1 2 3 4 5 6 day Fri 1 16 1 1 0 0 Sat 2 53 18 13 1 0 Sun 0 39 15 18 3 1 Thur 1 48 4 5 1 3 # Not many 1- and 6-person parties In [66]: party_counts = party_counts.ix[:, 2:5]

bubuko.com,布布扣
然后进行规格化,使得各行的和为1(必须转换成浮点数,以避免Python 2.7中的整数除法问题),并生成图表,如下所示:

# Normalize to sum to 1 In [68]: party_pcts = party_counts.div(party_counts.sum(1).astype(float), axis=0) In [69]: party_pcts Out[69]: size 2 3 4 5 day Fri 0.888889 0.055556 0.055556 0.000000 Sat 0.623529 0.211765 0.152941 0.011765 Sun 0.520000 0.200000 0.240000 0.040000 Thur 0.827586 0.068966 0.086207 0.017241 In [70]: party_pcts.plot(kind=‘bar‘, stacked=True)

bubuko.com,布布扣
说明:

通过该数据集可以看出,聚会规模在周末就会变大。

7、直方图和密度图

直方图(histogram)是一种可以对值频率进行离散化显示的柱状图。数据点被拆分到离散的、间隔均匀的面元中,绘制的是各面元中数据点的数量。再以前面那个小费数据为例,通过Series的hist方法,我们可以生成一张“小费占消费总额百分比”的直方图。

In [71]: tips[‘tip_pct‘] = tips[‘tip‘] / tips[‘total_bill‘] In [72]: tips[‘tip_pct‘].hist(bins=50)

更多干货分享加python编程语言学习QQ群 515267276

bubuko.com,布布扣

与此相关的一种图表类型是密度图,它是通过计算“可能会产生观测数据的连续概率分布的估计”而产生的。一般的过程是将该分布近似为一组核(即诸如正态(高斯)分布之类的较为简单的分布)。因此,密度图也被称作KDE(Kernel Density Estimate,核密度估计),如下所示:

In [73]: tips[‘tip_pct‘].plot(kind=‘kde‘)

bubuko.com,布布扣

这两种图表常常会被画在一起。直方图以规格化形式给出(以便给出面元化密度),然后再在其上绘制核密度估计。接下来来看一个由两个不同的标准正态分布组成的双峰分布,如下所示:

In [74]: comp1 = np.random.normal(0, 1, size=200) # N(0, 1) In [75]: comp2 = np.random.normal(10, 2, size=200) # N(10, 4) In [76]: values = pd.Series(np.concatenate([comp1, comp2])) In [77]: values.hist(bins=100, alpha=0.3, color=‘k‘, normed=True) Out[77]: In [78]: values.plot(kind=‘kde‘, style=‘k--‘)

bubuko.com,布布扣

8、散布图

散布图(scatter plot)是观察两个一维数组序列之间的关系的有效手段。matplotlib的scatter方法是绘制散布图的主要方法。在下面这个例子中,我加载了来自statsmodels项目的macrodata数据集,选择其中几列,然后计算对数差:

macrodata数据集:http://download.csdn.net/detail/shengshengwang/7198003

In [79]: macro = pd.read_csv(‘ch08/macrodata.csv‘) In [80]: data = macro[[‘cpi‘, ‘m1‘, ‘tbilrate‘, ‘unemp‘]] In [81]: trans_data = np.log(data).diff().dropna() In [82]: trans_data[-5:] Out[82]: cpi m1 tbilrate unemp 198 -0.007904 0.045361 -0.396881 0.105361 199 -0.021979 0.066753 -2.277267 0.139762 200 0.002340 0.010286 0.606136 0.160343 201 0.008419 0.037461 -0.200671 0.127339 202 0.008894 0.012202 -0.405465 0.042560

利用plt.scatter即可轻松绘制一张简单的散布图,如下所示:

In [83]: plt.scatter(trans_data[‘m1‘], trans_data[‘unemp‘]) Out[83]: In [84]: plt.title(‘Changes in log %s vs. log %s‘ % (‘m1‘, ‘unemp‘))

bubuko.com,布布扣
在探索式数据分析中,同时观察一组变量的散布图是很有意义的,这也被称为散布图矩阵(scatter plot matrix)。纯手工创建这样的图表很费工夫,所以pandas提供了一个能从DataFrame创建散布图矩阵的scatter_matrix函数。它还支持在对角线上放置各变量的直方图或密度图。如下所示:

In [85]: scatter_matrix(trans_data, diagonal=‘kde‘, color=‘k‘, alpha=0.3)

9、Python图形化工具生态系统

(1)Chaco

bubuko.com,布布扣

Chaco(http://code.enthought.com/chaco/)是由Enthought开发的一个绘图工具包,它既可以绘制静态图又可以生成交互式图形。它非常适合用复杂的图形化方式表达数据的内部关系。跟matplotlib相比,Chaco对交互的支持要好得多,而且渲染速度很快。如果要创建交互式的GUI应用程序,它确实是个不错的选择。

(2)mayavi

mayavi项目是一个基于开源C++图形库VKT的3D图形工具包。跟matplotlib一样,mayavi也能集成到IPython以实现交互式使用。通过鼠标和键盘进行操作,图形可以被平移、旋转、缩放。我相信它能成为WebGL(以及相关产品)的替代品,虽然其生成的图形很难以交互的形式共享。

(3)其他库

当然,Python领域中还有许多其他的图形化库和应用程序:PyQwt、Veusz、gnuplotpy、biggles等。我就曾经见过PyQwt被用在基于Qt框架(PyQt)的GUI应用程序中。许多库都还在不断地发展(有些已经被用在大型应用程序当中了)。近几年来,我发现了一个总体趋势:大部分库都在向基于Web的技术发展,并逐渐远离桌面图形技术。

(4)basemap工具集(http://matplotlib.github.com/basemap,matplotlib的一个插件)使得我们能够用Python在地图上绘制2D数据。basemap提供了许多不同的地球投影以及一种将地球上的经纬度坐标投影转换为二维matplotlib图的方式。

(5)图形化工具的未来

基于Web技术(比如JavaScript)的图形化是必然的发展趋势。毫无疑问,许多基于Flash或JavaScript的静态或交互式图形化工具已经出现了很多年,而且类似的新工具包(如d3.js及其分支项目)一直都在不断涌现。相比之下,非Web式的图形化开发工作在近几年中减慢了许多。Python以及其他数据分析和统计计算环境(如R)都是如此。于是,开发方向就变成了实现数据分析和准备工具(如pandas)与Web浏览器之间更为紧密的集成。

猜你喜欢

转载自blog.csdn.net/cqacry2798/article/details/84314814
今日推荐