《利用python進行數據分析》讀書筆記--第八章 繪圖和可視化

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

 

python有許多可視化工具,本書主要講解matplotlib。matplotlib是用於建立出版質量圖表的桌面繪圖包(主要是2D方面)。matplotlib的目的是爲了構建一個MATLAB式的繪圖接口。本書中的大部分圖都是用它生成的。除了圖形界面顯示,還能夠把圖片保存爲pdf、svg、jpg、png、gif等形式。python

一、matplotlib API入門ubuntu

Ipython能夠用close()關閉界面。數組

Figure和Subplotapp

matplotlib的圖像都位於Figure對象中。用plt.figure建立一個新的Figure。dom

複製代碼
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會自動縮放各圖表的界限。
複製代碼

看一下subplots的做用:svg

image

pyplot.subplots的選項還有:函數

image

上面的**fig_k能夠有不少的參數,文檔中有更多的內容。工具

調整subplot周圍的間距post

默認狀況下,matplotlib會在subplot外圍留下必定的邊距,並在subplot之間留下必定的間距。間距和圖像的高度和寬度有關,會自動調整。利用Figure的subplots——adjust方法能夠修改間距,所以,它是一個頂級函數。

複製代碼
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不會檢查標籤的重疊(確實是這樣)。
複製代碼
複製代碼
# -*- 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()
複製代碼

注意上面的drawstyle選項能夠規定點與點之間的鏈接方式,或者說是插值方式,結果爲:

image

設置標題、軸標籤、刻度以及刻度標籤

複製代碼
# -*- 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()
複製代碼

image

圖例

複製代碼
# -*- 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()
複製代碼

image

註解與繪圖

複製代碼
# -*- 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()
複製代碼

image

image

將圖表保存到文件

複製代碼
# -*- 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()
複製代碼

savefig的一些選項:

image

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是配置文件,定義好之後每次加載就會用設置的參數。

二、pandas中的繪圖函數

matplotlib是一種比較低級的工具,須要將各類組件組合好:數據展現(線型圖、柱狀圖等)、圖例、標題、刻度標籤以及註解。這是由於製做一張圖表通常須要用到多個對象。在pandas中,會省事很多。pandas可以利用DataFrame的對象特色建立標準圖表的高級繪圖方法。做者說pandas在線文檔時最好的學習工具,書上的代碼可能過期了。

線型圖

複製代碼
#-*- 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()
複製代碼

image

image

下面把參數貼一下:

image

image

DataFrame還有一些對列進行處理的參數:

image

自下面開始就有一些專門的圖形,繪製的時候能夠與R語言進行對比:http://www.cnblogs.com/batteryhp/p/4733474.html

柱狀圖

複製代碼
#-*- 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()
複製代碼

image

image

image

image

下面看一個例子:

複製代碼
#-*- 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()
複製代碼

image

直方圖和密度圖

複製代碼
#-*- 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()
複製代碼

image

image

image

散佈圖

散佈圖(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 參數,是爲了避免讓對角線上的圖形(本身和本身的散佈圖)顯示爲一條直線而設置的關於這種數據的某些圖形顯示
#好比 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()
複製代碼

image

image

image

繪製地圖:圖形化顯示海地地震危機數據

這是一個例子。

複製代碼
#-*- 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' )
複製代碼

因爲window下安裝geos不成功,這部分等ubuntu裝好了再接着寫。

四、Python圖形化工具生態系統

介紹幾個其餘的繪圖工具。

Chaco

特色:靜態圖 + 交互圖形,很是適合用複雜的圖形化方法表示數據的內部關係。對交互支持的好的多,交互式GUI是個不錯選擇。

mayavi

這是一個基於開源C++圖形庫VTK的3D圖形工具包。能夠集成到Ipython交互使用。

其餘庫

其餘庫或者應用還有:PyQwt、Veusz、gnuplotpy、biggles等,大部庫都在向基於Web的技術發展,並逐漸遠離桌面圖形技術。

圖形化工具的將來

基於Web技術(如Javascript)的圖形化是必然的發展趨勢,如今已經有很多了,higncharts等。

相關文章
相關標籤/搜索