《利用Python进行数据分析》第8章 绘图和可视化笔记

matplotlib绘图和可视化

matplotlib是一个用于创建出版质量图表的桌面绘图包(主要是2D方面)。绘图是数据分析工作中最重要的任务之一,是探索过程的一部分。

import matplotlib.pyplot as plt
from pandas import Series,DataFrame
import pandas as pd
import numpy as np
from numpy.random import randn
plt.plot(np.arange(15))
plt.show()

Figure和Subplot

fig=plt.figure()
ax1=fig.add_subplot(2,2,1)
ax2=fig.add_subplot(2,2,2)
ax3=fig.add_subplot(2,2,3)
plt.plot(np.random.randn(50).cumsum(),'k--')

"k--"是一个线型选项,用于告诉matplotlib绘制黑色虚线图。上面那些由fig.add_subplot所返回的对象是AxesSubplot对象,直接调用它们的实例方法就可以在其他空着的格子里面画图

_=ax1.hist(np.random.randn(100),bins=20,color='r',alpha=0.3)
ax2.scatter(np.arange(30),np.arange(30)+3*np.random.randn(30))
plt.show()

plt.subplots,它可以创建一个新的Figure,并返回一个含有已创建的subplot对象的NumPy数组

fig,axes=plt.subplots(2,3)
axes
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x0000000012981F98>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000000012835FD0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x00000000129EAFD0>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x000000001298C9B0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x00000000127EDA20>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x00000000125DBEB8>]], dtype=object)

调整subplot周围的间距

Figure的subplots_adjust方法可以修改间距

#subplots_adjust(left=None,bottom=None,right=None,top=None,wpace=None,hspace=None)
fig,axes=plt.subplots(2,2,sharex=True,sharey=True)
for i in range(2):
    for j in range(2):
        axes[i,j].hist(randn(500),bins=50,color='k',alpha=0.6)
        
plt.subplots_adjust(wspace=0,hspace=0)
plt.show()

颜色、标记和线型

matplotlib的plot函数接受一组X和Y坐标,还可以接受一个表示颜色和线型的字符串缩写

ax.plot(x,y,'g--')  #根据x和y绘制绿色虚线
ax.plot(x,y,linestyle='--',color='g')
plt.plot(np.random.randn(30).cumsum(),'ko--')
plt.show()

可以把它写成更为明确的方式

plt.plot(np.random.randn(30).cumsum(),color='b',linestyle='dashed',marker='o')
plt.show()
带有标记的线型图示例

在线型图中,非实际数据点默认是按线性方式插值的。可以通过drawstyle选项修改

data=np.random.randn(30).cumsum()
plt.plot(data,'k--',label='Default')
plt.show()
plt.plot(data,'k-',color='b',drawstyle='steps-post',label='steps-post')
plt.show()
plt.plot(data,'k-',color='b',drawstyle='steps-post',label='steps-post')
plt.legend(loc='best')
plt.show()

刻度、标签和图例

设置标题、轴标签、刻度以及刻度标签

创建一个简单的图像并绘制一段随机漫步

fig=plt.figure()
ax=fig.add_subplot(1,1,1)
ax.plot(np.random.randn(1000).cumsum())
plt.show()
演示xticks的简单线型图

可以使用set_xticks和set_xticklabels修改X轴的刻度

fig=plt.figure()
ax=fig.add_subplot(1,1,1)
ax.plot(np.random.randn(1000).cumsum())

#用set_xticks修改X轴的刻度
ticks=ax.set_xticks([0,250,500,750,1000])
#可以通过set_xticklabels将任何其他的值用作标签
labels=ax.set_xticklabels(['one','two','three','four','five'],rotation=30,fontsize='small')
#用set_title给图表设置一个标题
ax.set_title('My first matplotlib plot')
#为X轴设置一个名称
ax.set_xlabel('Stages')
plt.show()

添加图例(legend)

在添加subplot的时候传入label参数来添加图例

fig=plt.figure()
ax=fig.add_subplot(1,1,1)
ax.plot(np.random.randn(1000).cumsum(),'k',label='one',color='r')
ax.plot(np.random.randn(1000).cumsum(),'k--',label='two',color='g')
ax.plot(np.random.randn(1000).cumsum(),'k.',label='three',color='b')
ax.legend(loc='best')
plt.show()

调用ax.legend()或plt.legend()来自动创建图例

loc告诉matplotlib要将图例放在哪,'beat'里面可以显示确定的位置,如下:
best
upper right
upper left
lower left
lower right
right
center left
center right
lower center
upper center
center

如果要从图例中去除一个或多个元素,不传入label或传入label='nolegend'

注解以及在Subplot上绘图

注解可以是文本、箭头或其他图形等,通过text、arrow和annotate等函数进行添加。text可以将文本绘制在图表的指定坐标(x,y),还可以加上一些自定义格式

ax.text(x,y,"hello world!",Family='monospace',fontsize=10)

例如,我们根据2007年以来的标准普尔500指数收盘价格(来自Yahoo!Finance)绘制一张曲线图,并标出2008年到2009年金融危机期间的一些重要日期。结果如下图所示

from datetime import datetime
import pandas as pd
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='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')
    
# 放大到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')
plt.show()
图2008-2009年金融危机期间的重要日期

要在图表中添加一个图形,你需要创建一个块对象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='r',alpha=0.6)
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)
plt.show()

将图表保存到文件

利用plt.savefig可以将当前图表保存到文件。该方法相当于Figure对象的实例方法savefig

plt.savefig('figpath.svg')

在发布图片时最常用到两个重要的选项是dpi(控制“每英寸点数”分辨率)和bbox_inches(可以剪除当前图表周围的空白部分)。要得到一张带有最小白边且分辨率为400DPI的PNG图片可以这样做:

plt.savefig('figpath.png',dpi=400,bbox_inches='tight')

savefig并非一定要写入磁盘,也可以写入任何文件型的对象,比如StringIO。其中,这个在Web上提供动态生成的图片是很实用

from io import StringIO
plt.savefig(buffer)
plot_data=buffer.getvaule()

matplotlib配置

matplotlib自带一些配色方案,以及为生成出版质量的图片而设定的默认配置信息,可以管理图像大小、subplot边距、配色方案、字体大小、网格类型等。操作matplotlib配置系统的方式主要有两种。第一种是Python编程方式,即利用rc方法

将全局的图像默认大小设置为10×10

plt.rc('figure',figsize=(10,10))

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

font_opinions={'family':'monospace','weight':'bold','size':'samll'}
plt.rc('font',**font_options)

pandas中的绘图函数

pandas在线文档将会是最好的绘图函数学习资源。

线型图

Series对象的索引会被传给matplotlib,并用以绘制X轴。可以通过use_index=False禁用该功能。
X轴的刻度和界限可以通过xticks和xlim选项进行调节,Y轴就用yticks和ylim

s=Series(np.random.randn(10).cumsum(),index=np.arange(0,100,10))
s.plot()
plt.show()

pandas的大部分绘图方法都有一个可选的ax参数,它可以是一个matplotlib的subplot对象。这使你能够在网格布局中更为灵活地处理subplot的位置。
DataFrame的plot方法会在一个subplot中为各列绘制一条线,并自动创建图例。

df=DataFrame(np.random.randn(10,4).cumsum(0),columns=['A','B','C','D'],index=np.arange(0,100,10))
df.plot()
plt.show()

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

柱状图

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

fig,axes=plt.subplots(2,1)
data=Series(np.random.rand(16),index=list('abcdefghijklmnop'))
data.plot(kind='bar',ax=axes[0],color='g',alpha=0.6)
data.plot(kind='barh',ax=axes[1],color='g',alpha=0.6)
plt.show()

对于DataFrame,柱状图会将每一行的值分为一组

df=DataFrame(np.random.rand(6,4),index=['one','two','three','four','five','six'],columns=['A','B','C','D'])
df
A B C D
one 0.381932 0.042627 0.290334 0.700356
two 0.212308 0.519060 0.241667 0.653755
three 0.223746 0.233344 0.714892 0.620117
four 0.401946 0.862935 0.874891 0.862926
five 0.680490 0.879683 0.562349 0.036203
six 0.791145 0.873458 0.604575 0.479191
df.plot(kind='bar')
plt.show()

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

提示:柱状图有一个非常不错的用法:利用value_counts图形化显示Series中各值的出现频率,比如s.value_counts ().plot(kind='bar')。

df.plot(kind='barh',stacked=True,alpha=0.8)
plt.show()

以本书的有关小费的数据集为例,假设我们想要做一张堆积柱状图以展示每天各种聚会规模的数据点的百分比。我用read_csv将数据加载进来,然后根据日期和聚会规模创建一张交叉表

tips=pd.read_csv('examples/tips.csv')
#如果通过tips.size,取到的是一整列的和
party_counts=pd.crosstab(tips.day,tips['size'])
party_counts
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

进行规格化,使得各行的和为1(必须转换成浮点数),并生成图表

party_counts=party_counts.ix[:,2:5]# 1个人和6个人的聚会都比较少
party_pcts=party_counts.div(party_counts.sum(1).astype(float),axis=0)
party_pcts
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

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

直方图和密度图

直方图(histogram)是一种可以对值频率进行离散化显示的柱状图。数据点被拆分到离散的、间隔均匀的面元中,绘制的是各面元中数据点的数量

以前面那个小费数据为例,通过Series的hist方法,我们可以生成一张“小费占消费总额百分比”的直方图

tips['tip_pct']=tips['tip']/tips['total_bill']
tips['tip_pct'].hist(bins=50)
plt.show()
小费百分比的直方图

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

调用plot时加上kind='kde'即可生成一张密度图(标准混合正态分布KDE)

tips['tip_pct'].plot(kind='kde')
plt.show()
小费百分比的密度图

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

comp1=np.random.normal(0,1,size=200)#N(0,1)
comp2=np.random.normal(10,2,size=200)# (10,4)
values=Series(np.concatenate([comp1,comp2]))
values.hist(bins=100,alpha=0.3,color='g',normed=True)
values.plot(kind='kde',style='k--')
plt.show()

散布图

散布图(scatter plot)是观察两个一维数据序列之间的关系的有效手段。matplotlib的scatter方法是绘制散布图的主要方法

通过例子看看,首先加载了来自statsmodels项目的macrodata数据集,选择其中几列,然后计算对数差

macro=pd.read_csv('examples/macrodata.csv')
data=macro[['cpi','m1','tbilrate','unemp']]
trans_data=np.log(data).diff().dropna()
trans_data[-5:]
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即可轻松绘制一张简单的散布图

plt.scatter(trans_data['m1'],trans_data['unemp'])
plt.title('Cahnges in log %s vs. log %s '%('m1','unemp'))
plt.show()

散布图矩阵(scatter plot matrix)。
pandas提供了一个能从DataFrame创建散布图矩阵的scatter_matrix函数。它还支持在对角线上放置各变量的直方图或密度图

pd.scatter_matrix(trans_data,diagonal='kde',alpha=0.3)
plt.show()
e:\python\lib\site-packages\ipykernel_launcher.py:1: FutureWarning: pandas.scatter_matrix is deprecated. Use pandas.plotting.scatter_matrix instead
  """Entry point for launching an IPython kernel.

通过练习python matplotlib可视化的知识,学习到对数据绘图的基础知识,了解到matplotlib其他的绘图接口 seaborn和 ggplot。
完善并深入练习还是需要去官方网站去查看相关的用法。
有兴趣可以去官网查看手册:https://matplotlib.org/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容