利用python进行数据分析 笔记_《利用python进行数据分析》读书笔记--第八章 绘图和可视化...

http://www.cnblogs.com/batteryhp/p/5025772.html

python有许多可视化工具,本书主要讲解matplotlib。matplotlib是用于创建出版质量图表的桌面绘图包(主要是2D方面)。matplotlib的目的是为了构建一个MATLAB式的绘图接口。本书中的大部分图都是用它生成的。除了图形界面显示,还可以把图片保存为pdf、svg、jpg、png、gif等形式。

1、matplotlib API入门

Ipython可以用close()关闭界面。

Figure和Subplot

matplotlib的图像都位于Figure对象中。用plt.figure创建一个新的Figure。

copycode.gif

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

'''

#plt.plot(np.arange(10))

fig = plt.figure()

#plt.show()

#figsize 有一些重要的选项,特别是figsize,规定的是图片保存到磁盘时具有一定大小的纵横比。

#plt.gcf()即可得到当前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--')

#fig.add_subplot 返回的对象是AxesSubplot对象,下面调用就可以了

_ = ax1.hist(np.random.randn(100),bins = 20,color = 'k',alpha = 0.3)

ax2.scatter(np.arange(30),np.arange(30) + 3 * np.random.randn(30))

plt.show()

'''

#由于Figure 和 subplot是一件非常常见的任务,于是出现了更为方便的方法(plt.subplots ),它可以创建一个新的Figure,

#并返回一个含有已创建的subplot对象的Numpy数组

fig,axes = plt.subplots(2,3)

#print fig

print axes[0][0]

#axes[0][0].hist(np.random.randn(100),bins = 20,color = 'k',alpha = 0.3)

plt.show()

#这是非常实用的,因为可以轻松地对axes数组进行索引,就好像一个是一个二维数组一样,例如

#axes[0,1].还可以通过sharex和sharey指定subplot具有相同的x轴和y轴。在比较相同范围的数据时,这是

#非常实用的,否则matplotlib会自动缩放各图表的界限。

copycode.gif

看一下subplots的作用:

750792-20151207222531433-495624178.png

pyplot.subplots的选项还有:

750792-20151207222532980-1585500767.png

上面的**fig_k可以有很多的参数,文档中有更多的内容。

调整subplot周围的间距

默认情况下,matplotlib会在subplot外围留下一定的边距,并在subplot之间留下一定的间距。间距和图像的高度和宽度有关,会自动调整。利用Figure的subplots——adjust方法可以修改间距,因此,它是一个顶级函数。

copycode.gif

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

subplots_adjust(left = None,bottom = None,right = None,top = None,wspace = None,hspace = None)

#wspace和space用于控制宽度和高度的百分比,可以用做subplot之间的间距,下面是个例子:

'''

fig,ax = plt.subplots(2,2,sharex = True,sharey = True)

for i in range(2):

for j in range(2):

ax[i,j].hist(np.random.randn(500),bins = 50,color = 'k',alpha = 0.5)

plt.subplots_adjust(wspace = 0.5,hspace = 0.5)

plt.show()

#matplotlib不会检查标签的重叠(确实是这样)。

copycode.gif

copycode.gif

# -*- encoding: UTF-8 -*-

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

fig,ax = plt.subplots(2,2)

#cecece是白色……

ax[0,0].plot(np.arange(10),linestyle = '--',color = '#CECECE')

#线上面还可以添加一些标记(marker),以强调实际的数据点。由于matplotlib创建的是连续的线形图,因此有时可能不太容易看到真实点的位置,标记可以放到格式字符串中,但是标记类型和线性必须在颜色的后面

ax[0,1].plot(np.random.randn(30).cumsum(),'ko--')

ax[1,0].plot(np.random.randn(30).cumsum(),color = 'k',linestyle = '--',marker = 'o')

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

data = np.random.randn(30).cumsum()

ax[1,1].plot(data,'ko--')

ax[1,1].plot(data,'k--',drawstyle = 'steps-post')

plt.show()

copycode.gif

注意上面的drawstyle选项可以规定点与点之间的连接方式,或者说是插值方式,结果为:

750792-20151208134356761-1530937226.png

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

copycode.gif

# -*- encoding: UTF-8 -*-

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

import numpy.random as npr

fig = plt.figure()

ax = fig.add_subplot(1,1,1)

ax.plot(npr.randn(1000).cumsum())

#要想修改x的刻度,最简单的方法就是使用set_xticks和set_xticklabels.前者告诉matplotlib将

#刻度放在数据范围中的哪些位置,默认情况下,这些位置就是刻度标签。但是可以使用set_xticklabels将#任何其他的值用作标签

ticks = ax.set_xticks([0,250,500,700,900,1000])

#下面的totation是规定旋转角度

labels = ax.set_xticklabels(['a','b','c','d','e','f'],rotation = 30,fontsize = 'small')

#可以为x轴设置名称

ax.set_xlabel('Stages')

plt.show()

copycode.gif

750792-20151208134359715-361710468.png

图例

copycode.gif

# -*- encoding: UTF-8 -*-

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

import numpy.random as npr

from datetime import datetime

#添加图例

fig = plt.figure()

ax = fig.add_subplot(1,1,1)

ax.plot(npr.randn(1000).cumsum(),'k',label = 'one')

ax.plot(npr.randn(1000).cumsum(),'k--',label = 'two')

ax.plot(npr.randn(1000).cumsum(),'k.',label = 'three')

ax.legend(loc = 'best')

plt.show()

copycode.gif

750792-20151208215637527-607098647.png

注解与绘图

copycode.gif

# -*- encoding: UTF-8 -*-

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

import numpy.random as npr

from datetime import datetime

fig = plt.figure()

ax = fig.add_subplot(1,1,1)

data = pd.read_csv('E:\\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')

ax.set_xlim(['1/1/2007','1/1/2011'])

ax.set_ylim([600,1800])

ax.set_title('Important dates in 2008-2009 finacial crisis')

plt.show()

#更多关于注解的示例,请看文档

#图形的绘制要麻烦些,有一些常见的图形的对象,这些对象成为块(patch)

#如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)

plt.show()

copycode.gif

750792-20151208215640090-802970550.png

750792-20151208215641683-1810923034.png

将图表保存到文件

copycode.gif

# -*- encoding: UTF-8 -*-

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

import numpy.random as npr

from datetime import datetime

from io import StringIO

#将图标保存到文件

#savefig函数可以保存图形文件,不同的扩展名保存为不同的格式

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)

#注意下面的dpi(每英寸点数)和bbox_inches(可以剪除当前图标周围的空白部分)(确实有效)

#plt.savefig('pic.jpg',dpi = 100,bbox_inches = 'tight')

#不一定save到文件中,也可以写入任何文件型对象,比如StringIO:

buffer = StringIO()

plt.savefig(buffer)

plot_data = buffer.getvalue()

#这对Web上提供动态生成的图片是很实用的

#plt.show()

copycode.gif

savefig的一些选项:

750792-20151208215643652-94782071.png

matplotlib配置

matplotlib的一些属性是可以设置的,比如图像大小、subplot边距、配色方案、字体大小、网格类型等。有两种方式进行操作。第一种是Python变成方式,即利用rc方法。比如:

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)

matplotlibrc是配置文件,定义好以后每次加载就会用设置的参数。

2、pandas中的绘图函数

matplotlib是一种比较低级的工具,需要将各种组件组合好:数据展示(线型图、柱状图等)、图例、标题、刻度标签以及注解。这是因为制作一张图表一般需要用到多个对象。在pandas中,会省事不少。pandas能够利用DataFrame的对象特点创建标准图表的高级绘图方法。作者说pandas在线文档时最好的学习工具,书上的代码可能过时了。

线型图

copycode.gif

#-*- encoding:utf-8 -*-

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pandas import Series,DataFrame

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

#该Series对象的索引会被传给matplotlib,并绘制X轴。

#可以用use_index = False 禁用该功能

s.plot(use_index = False)

#X轴的刻度和界限可以通过xticks和xlim选项进行调节,Y轴通过xticks和ylim调节

plt.show()

#pandas的大部分方法都有一个可选的ax参数,可以是一个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()

copycode.gif

750792-20151209000954527-1738413966.png

750792-20151209000956683-1011701053.png

下面把参数贴一下:

750792-20151209000959058-1399355056.png

750792-20151209001001152-1637556628.png

DataFrame还有一些对列进行处理的参数:

750792-20151209001003668-175080431.png

柱状图

copycode.gif

#-*- encoding:utf-8 -*-

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pandas import Series,DataFrame

#生成的线形图中代码加上kind = ‘bar’(垂直柱图) 或者 (水平)kind = ‘barh’(水平柱图)

#Series和DataFrame的索引被用作X(bar)或者Y(barh)的刻度

fig,axes = plt.subplots(2,1)

data = Series(np.random.randn(16),index = list('abcdefghijklmnop'))

data.plot(kind = 'barh',ax = axes[0],color = 'k',alpha = 0.7)

data.plot(kind = 'bar',ax = axes[1],color = 'k',alpha = 0.7)

#DataFrame会按照行对数据进行分组

df = DataFrame(np.random.randn(6,4),index = ['one','two','three','four','five','six'],

columns = pd.Index(['A','B','C','D'],name = 'Genus'))

#注意这里的name会被用作图例的标题,因为,这本来就是列的名字

print df

df.plot(kind = 'bar')

plt.show()

#这里的stacked是标明画累计柱图

df.plot(kind = 'bar',stacked = True,alpha = 0.5)

plt.show()

#Series的value_counts可以用来显示Series中各值的频数(实验证明)

s = Series([1,2,2,3,4,4,4,5,5,5])

s.value_counts().plot(kind = 'bar')

plt.show()

copycode.gif

750792-20151209001006277-340318907.png

750792-20151209001008308-1188340293.png

750792-20151209001010761-1201950044.png

750792-20151209001013433-1711021661.png

下面看一个例子:

copycode.gif

#-*- encoding:utf-8 -*-

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pandas import Series,DataFrame

#下面是一个例子:做一张堆积柱状图来显示每天各种聚会规模的数据点百分比

tips = pd.read_csv('E:\\tips.csv')

party_counts = pd.crosstab(tips.day,tips.size)

print party_counts

party_counts = party_counts.ix[:,2:5]

#然后进行归一化是各行和为1

party_pcts = party_counts.div(party_counts.sum(1).astype(float),axis = 0)

print party_pcts

party_pcts.plot(kind = 'bar',stacked = True)

plt.show()

copycode.gif

750792-20151209005029215-1944357279.png

直方图和密度图

copycode.gif

#-*- encoding:utf-8 -*-

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pandas import Series,DataFrame

#绘制小费百分比直方图

tips = pd.read_csv('E:\\tips.csv')

tips['tip_pct'] = tips['tip'] / tips['total_bill']

#bins规定一共分多少个组

tips['tip_pct'].hist(bins = 50)

plt.show()

#与此相关的是密度图:他是通过计算“可能会产生观测数据的连续概率分布的估计”

#而产生的。一般的过程将该分布金思维一组核(诸如正态之类的较为简单的分布)。

#此时的密度图称为KDE图。kind = ‘kde’即可。

tips['tip_pct'].plot(kind = 'kde')

plt.show()

#显然,直方图和密度图经常会在一起出现

comp1 = np.random.normal(0,1,size = 200)

comp2 = np.random.normal(10,2,size = 200)

values = Series(np.concatenate([comp1,comp2]))

print values

values.hist(bins = 100,alpha = 0.3,color = 'k',normed = True)

values.plot(kind = 'kde',style = 'k--')

plt.show()

copycode.gif

750792-20151209005030293-586408117.png

750792-20151209005031621-926004727.png

750792-20151209005032793-104759950.png

散布图

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

copycode.gif

#-*- encoding:utf-8 -*-

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pandas import Series,DataFrame

#下面加载macrodata中的数据集,选择其中几列并计算对数差

macro = pd.read_csv('E:\\macrodata.csv')

data = macro[['cpi','m1','tbilrate','unemp']]

#这里的diff函数是用来计算相邻两数只差,对每一列,后一个数减前一个数

trans_data = np.log(data).diff().dropna()

#print np.log(data).head()

#print np.log(data).diff().head()

print trans_data.head()

plt.scatter(trans_data['m1'],trans_data['unemp'])

plt.title('Changes in log %s vs. log %s'%('m1','unemp'))

plt.show()

#画散布图矩阵式很有意义的pandas提供了scantter_matrix函数来创建散步矩阵

#关于 diagonal 参数,是为了不让对角线上的图形(自己和自己的散布图)显示为一条直线而设置的关于这种数据的某些图形显示

#比如 diagonal = 'kde'就是画密度图且核为kde,若diagonal='hist',则为直方图

pd.scatter_matrix(trans_data,diagonal = 'kde',color = 'k',alpha = 0.3)

pd.scatter_matrix(trans_data,diagonal = 'hist',color = 'k',alpha = 0.3)

plt.show()

copycode.gif

750792-20151209011601933-586677653.png

750792-20151209011603246-639114507.png

750792-20151209011604652-663140373.png

绘制地图:图形化显示海地地震危机数据

这是一个例子。

copycode.gif

#-*- encoding:utf-8 -*-

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pandas import Series,DataFrame

from mpl_toolkits.basemap import Basemap

#下面的例子应该是比较综合的

data = pd.read_csv('E:\\Haiti.csv')

#print data

#下面处理一下数据,下面的为日期,纬度、经度

#print data[['INCIDENT DATE','LATITUDE','LONGITUDE']][:10]

#print data['CATEGORY'][:6] #这些代表消息的类型

#数据中很有可能有异常值、缺失值,下面看一下

#print data.describe()

#清除错误信息并移除缺失分类信息是“一件简单的事情”

data = data[(data.LATITUDE > 18) & (data.LATITUDE < 20) & (data.LONGITUDE > -75) &

(data.LONGITUDE < -70) & data.CATEGORY.notnull()]

#我们想根据分类对数据做一些分析或者图形化工作,但是各个分类字段中可能含有多个分类。此外,各个分类信息

#不仅有一个编码,还有一个英语(法语)名称。因此需要对数据进行规整化处理。下面编写两(三)个

#函数,一个用于获取所有分类的列表,一个用于将各个分类信息拆分为编码和英语明名称

#sptrip 是删除空白字符,'\n'等;注意作者这种隐式循环写法

def to_cat_list(catstr):

stripped = (x.strip() for x in catstr.split(','))

return [x for x in stripped if x]

def get_all_categoties(cat_series):

cat_sets = (set(to_cat_list(x)) for x in cat_series)

return sorted(set.union(*cat_sets))

def get_english(cat):

code,names = cat.split('.')

if '|' in names:

names = names.split('|')[1]

return code,names.strip()

#下面进行一下ceshi

#print get_english('2.Urgences logistiques | Vital Lines')

#接下来做了一个将编码跟名称映射起来的字典,这是因为我们等会要用编码进行分析。

#下面将所有组合弄出来

all_cats = get_all_categoties(data.CATEGORY)

#print data.CATEGORY[:10]

#print all_cats

#生成器表达式

#生成字典

english_mapping = dict(get_english(x) for x in all_cats)

#print english_mapping['2a']

#print english_mapping['6c']

#根据分类选取记录的方式有很多,其中之一就是添加指标(或者哑变量)列,每个分类一列。

#为此,首先抽取出唯一的分类编码,并构造一个全零DataFrame(列为分类编码,索引跟data的索引一样)

def get_code(seq):

return [x.split('.')[0] for x in seq if x]

#下面是将所有的key取出来

all_codes = get_code(all_cats)

#print all_codes

code_index = pd.Index(np.unique(all_codes))

#print code_index

dummy_frame = DataFrame(np.zeros((len(data),len(code_index))),index = data.index,columns = code_index)

#print len(data)

#print dummy_frame.ix[:,:6]

#下面将各行中适当的项设置为1,然后再与data进行连接:

for row,cat in zip(data.index,data.CATEGORY):

codes = get_code(to_cat_list(cat))

dummy_frame.ix[row,codes] = 1

#添加前缀,并且合并一下

data = data.join(dummy_frame.add_prefix('category_'))

#print data

#接下来开始画图吧,我们希望把数据绘制在海地的地图上。basemap数据集是matplotloib的一个插件

#使得能够用Python在地图上绘制2D数据。basemap提供了许多不同的地球投影以及一种将地球上的经纬度

#坐标投影转换为二维matplotlib图的方式。

#“经过一遍又一遍的尝试”,作者编写了下面的函数,绘制出一张简单的黑白地图。

def basic_haiti_map(ax = None,lllat = 17.25,urlat = 20.25,lllon = -75,urlon = -71):

#创建极球面投影的Basemap实例。

m = Basemap(ax = ax,projection = 'stere',

lon_0 = (urlon + lllon) / 2,

lat_0 = (urlat + lllat) / 2,

llcrnrlat = lllat,urcrnrlat = urlat,

llcrnrlon = lllon,urcrnrlon = urlon,

resolution = 'f' )

copycode.gif

由于window下安装geos不成功,这部分等ubuntu装好了再接着写。

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

介绍几个其他的绘图工具。

Chaco

特点:静态图 + 交互图形,非常适合用复杂的图形化方法表示数据的内部关系。对交互支持的好的多,交互式GUI是个不错选择。

mayavi

这是一个基于开源C++图形库VTK的3D图形工具包。可以集成到Ipython交互使用。

其他库

其他库或者应用还有:PyQwt、Veusz、gnuplotpy、biggles等,大部库都在向基于Web的技术发展,并逐渐远离桌面图形技术。

图形化工具的未来

基于Web技术(如Javascript)的图形化是必然的发展趋势,现在已经有不少了,higncharts等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值