pandas 绘图函数

1. pandas 绘图函数

pandas有许多能够利用DataFrame对象数据组织特点来创建标准图表的高级绘图方法

线型图:

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

import numpy as np
import pandas as pd
from pandas import DataFrame,Series
import matplotlib.pyplot as plt

(1)Series的plot
s=Series(np.random.randn(10).cumsum(),index=np.arange(0,100,10))
s.plot()
plt.show()
#Series对象的索引会被传给matplotlib,并用以绘制X轴。可以通过user_index=False禁用该功能
#X轴的刻度和界限可以通过xticks和xlim选项进行调节,Y轴就用yticks和ylim.

(2)DataFrame的plot
#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()

Series.plot方法的参数:
参数                说明
label               用于图例的标签
ax                  要在其上进行绘制的matplotlib subplot对象。如果没有设置,则使用当前matplotlib subplot对象。
                    如果没有设置,则使用当前matplotlib subplot对象。
style               将要传给matplotlib的风格字符串(如‘ko--’)
alpha               图表的填充不透明度(0到1之间)
kind                可以是line,bar,barh,kde
logy                在Y轴上使用对数标尺
use_index           将对象的索引用作刻度标签
rot                 旋转刻度标签(0 到 360)
xticks              用作X轴刻度的值
yticks              用作Y轴刻度的值
xlim                X轴的界限(例如[0,10])
ylim                Y轴的界限

grid                显示轴网格线(默认打开)

DataFrame.plot方法的参数:

参数                 说明
subplots            将各个DataFrame列绘制到单独的subplot中
sharex              如果subplots=True,则共用同一个X轴,包括刻度和界限
sharey              如果subplots=True,则共用同一个Y轴
figsize             表示图像大小的元组
title               表示图像标题的字符串
legend              添加一个subplot图例(默认为True)

sort_columns        以字母表顺序绘制各列,默认使用当前列顺序

注:matplotlib.pyplot的一些方法可以参照pandas 绘图中matplotlib的那章

柱状图:

只要将kind='bar'(垂直柱状图)或kind='barh'(水平柱状图)即可生成柱状图。这时,Series和DataFrame

的索引将会被用作X(bar)或Y(barh)刻度:

import numpy as np
import pandas as pd
from pandas import DataFrame,Series
import matplotlib.pyplot as plt

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

(1) Stacked=True即可为DataFrame生成堆积柱状图,这亲每行的值就会被堆积在一块。

(2)value_counts图形化显示Series中各值的出现频率

import numpy as np
import pandas as pd
from pandas import DataFrame,Series
import matplotlib.pyplot as plt

#DataFrame会按照行对数据进行分组
fig,axes=plt.subplots(1,1)  #窗口只有一个子图,并且画在第一个图上
data=DataFrame(np.random.randn(6,4),index=['one','two','three','four','five','six'],
               columns=pd.Index(['A','B','C','D'],name='Genus'))
print data
data.plot(kind='bar')
plt.show()
#这里的stacked是标明画累计柱图
data.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()

下面再看一个例子:

#-*- 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()

直方图和密度图:

#-*- 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])) #concatenate连接两个数据为一个Series,和concate差不多
print values
values.hist(bins = 100,alpha = 0.3,color = 'k',normed = True)
values.plot(kind = 'kde',style = 'k--')
plt.show()

散布图:

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

#-*- 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 参数,是为了不让对角线上的图形(自己和自己的散布图)显示为一条直线而设置的关于这种数据的某些图形显示
# digonal参数是表示在对角线上放置各变量的直方图或密度图。
#比如 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()

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

由于Basemap未安装成功,无法显示下面的图形

import numpy as np
import pandas as pd
from pandas import DataFrame,Series
import matplotlib.pyplot as plt

#(1)先将csv文件的数据加载到DataFrame中
data=pd.read_csv('/Users/mac/PycharmProjects/python2.7/BigData/pydata-book-2nd-edition/datasets/haiti/Haiti.csv')
# print data

#(2)处理一下这些数据,看看哪些是我们想要的。每一行表示一条数据,每条数据都有一个时间戳和位置(经度和纬度)
# print data[['INCIDENT DATE','LATITUDE','LONGITUDE']][:10]
#输出结果如下:
#      INCIDENT DATE   LATITUDE   LONGITUDE
# 0  05/07/2010 17:26  18.233333  -72.533333
# 1  28/06/2010 23:06  50.226029    5.729886
# 2  24/06/2010 16:21  22.278381  114.174287
# 3  20/06/2010 21:59  44.407062    8.933989
# 4  18/05/2010 16:26  18.571084  -72.334671
# 5  26/04/2010 13:14  18.593707  -72.310079
# 6  26/04/2010 14:19  18.482800  -73.638800
# 7  26/04/2010 14:27  18.415000  -73.195000
# 8  15/03/2010 10:58  18.517443  -72.236841
# 9  15/03/2010 11:00  18.547790  -72.410010

#(3)Category字段含有一组以逗号分隔的代码,这些代码表示消息的类型:
# print data['CATEGORY'][:6]
# 输出结果如下:
# 0          1. Urgences | Emergency, 3. Public Health,
# 1    1. Urgences | Emergency, 2. Urgences logistiqu...
# 2    2. Urgences logistiques | Vital Lines, 8. Autr...
# 3                            1. Urgences | Emergency,
# 4                            1. Urgences | Emergency,
# 5                       5e. Communication lines down,
# Name: CATEGORY, dtype: object

#(4)调用describe还能发现数据中存在一些异常的地址位置
# print data.describe()
#输出结果如下:
#             Serial     LATITUDE    LONGITUDE
# count  3593.000000  3593.000000  3593.000000
# mean   2080.277484    18.611495   -72.322680
# std    1171.100360     0.738572     3.650776
# min       4.000000    18.041313   -74.452757
# 25%    1074.000000    18.524070   -72.417500
# 50%    2163.000000    18.539269   -72.335000
# 75%    3088.000000    18.561820   -72.293570
# max    4052.000000    50.226029   114.174287

#(5)消除错误位置信息,并移除缺失分类信息的数据
data=data[(data.LATITUDE > 18) & (data.LATITUDE <20) &
          (data.LONGITUDE > -75) & (data.LONGITUDE < -70) &
            data.CATEGORY.notnull()]

#(5)现在我们想根据分类对数据做一些分析或图形化工作,但是各个分类字段中可能含有多个分类。
#此外各个分类信息不仅有一个编码,还有一个英文名称(可能还有一个法语名称)。因此需要对
#数据做一些规整化处理。首先,编写两个函数,一个用于获取所有分类的列表,另一个用于
# 将各个分类信息拆分为编码和英语名称
#注意作者的一些隐式循环写法
print '++++++++++++++++++++++++++++++++++++'
def to_cat_list(catstr):
    stripped=(x.strip() for x in catstr.split(','))
    return [x for x in stripped if x]
def get_all_categories(cat_series):
    cat_set=(set(to_cat_list(x)) for x in cat_series)  #set集合是无序的
    return sorted(set.union(*cat_set)) #cat_set是一个可迭代的数组,故*cat_set
# a="a,b,c"
# print get_all_categories(a)
def get_english(cat):
    code,names=cat.split('.')
    if '|' in names:
        names=names.split('|')[1]
    return code,names.strip()
#测试一下get_english函数是否工作正常:
print get_english('4e. Assainissement eau et hygiene | Water sanitation and hygiene')
#输出结果如下:
# ('4e', 'Water sanitation and hygiene')

#(6)接下来,做了一个将编码和名称映射起来的字典,因为我们等会要用编码进行分析。后面我们在修饰图表时也会用到这个
#注意:这里用的是生成器表达式,而不是列表推导式。
# print data.CATEGORY
#生成字典
all_cats=get_all_categories(data.CATEGORY) #获取了category的所有列表
#生成器表达式,
english_mappling=dict(get_english(x) for x in all_cats)
# print english_mappling['2a']
#输出结果:Food Shortage
# print english_mappling['6c']
#输出结果:Earthquake and aftershocks

#(7)根据分类选取记录的方式有很多,其中之一是添加指标列,每个分类一列。为此,我们首先抽取出唯一的分类编码,
#并构造一个全零DataFrame(列为分类编码,索引跟data的索引一样)
def get_code(seq):
    return [x.split('.')[0] for x in seq if x]
#下面是将所有的key取出来
all_code=get_code(all_cats)
# print all_code
#输出结果如下:
# ['1', '1a', '1b', '1c', '1d', '2', '2a'】
code_index=pd.Index(np.unique(all_code)) #Index后面DataFrame中的行/列,去重
dummy_frame=DataFrame(np.zeros((len(data),len(code_index))),index=data.index, #行为数据的行索引
                      columns=code_index) #创建行X列为(len(data),len(code_index))的全零的DataFrame
# print dummy_frame.ix[:,:6] #ix取行索引,全部数据的,前6行
#输出结果如下:
#         1   1a   1b   1c   1d    2
# 0     0.0  0.0  0.0  0.0  0.0  0.0
# 4     0.0  0.0  0.0  0.0  0.0  0.0
# 5     0.0  0.0  0.0  0.0  0.0  0.0
# 6     0.0  0.0  0.0  0.0  0.0  0.0


#(8)现在应该将各行中适当的项设置为1,然后再与data进行连接
for row,cat in zip(data.index,data.CATEGORY):
    # print row,cat   #输出:3553 8e. Nouvelles de Personnes | Persons News,
    codes=get_code(to_cat_list(cat))
    dummy_frame.ix[row,codes]=1
    # print dummy_frame[:5]
#添加前缀,并且合并一下
data=data.join(dummy_frame.add_prefix('category_')) #category_0,category_1...
print data.ix[:,10:15]
#输出结果如下:
#       category_1  category_1a  category_1b  category_1c  category_1d
# 0            1.0          0.0          0.0          0.0          0.0
# 4            1.0          0.0          0.0          0.0          0.0
# 5            0.0          0.0          0.0          0.0          0.0

#(9)接下来开始画图,由于这是空间坐标数据,因此我们希望把数据绘制在海地的地图上。
#使用basemap工具集使得我们能够用python在地图上绘制2D数据。basemap提供了许多没的地球投影
#以及一种将地球上的经纬度坐标投影转换为二维matplotlib图的方式
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
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')
    #绘制海岸线、州界、国界及地图边界
    m.drawcoastlinew()
    m.drawstates()
    m.drawcountries()
    return m


#(11)现在问题是:如何让返回的这个Basemap对象知道该怎样将坐标转换到画布上。
#对于每一个分类,我在数据集中找到了对应的坐标,并在适当的subplot中绘制一个Basemap,转换坐标,
#然后通过Basemap的plot方法绘制点:
fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(12,10))
print fig,axes
fig.subplots_adjust(hspace=0.05,wspace=0.05)
to_plot=['2a','1','3c','7a']
lllat=17.25
urlat=20.25
lllon=-75
urlon=-71
for code,ax in zip(to_plot,axes.flat):
    m=basic_haiti_map(ax,lllat=lllat,urlat=urlat,
                      lllon=lllon,urlon=urlon)
    cat_data=data[data['category_%s' % code]==1]
    #计算地图的投影坐标
    x,y=m(cat_data.LONGITUDE,cat_data.LATITUDE)

    m.plot(x,y,'k.',alpha=0.5)
    ax.set_title('%s:%s' % (code,english_mappling[code]))

Chaco

还有一些可以绘制静太图又可以生成交互式图形的绘图工具包有:Chaco,mayavi,pyQwt,Veusz,gnuplot-py,biggles等.
chaco对交互的支持要好得多,而且渲染速度很快,如果要创建交互式的GUI应用程序,它确实是个不错的选择。web式的图形化
是后面的发展方向(如javascript),于是开发方向就变成了实现数据分析和准备工具(如pandas)与web浏览器之间更为紧密的
集成。

猜你喜欢

转载自blog.csdn.net/u012474716/article/details/81019218
今日推荐