1. 程式人生 > >pandas 繪圖函式

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瀏覽器之間更為緊密的
整合。