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