常見的圖表有:餅狀圖,柱狀圖(可並列),折線圖,散點圖,直方圖,疊加柱狀圖,三維散點圖,三維曲面圖,箱線圖。
下面用seaborn庫繪制以上各種類型的圖表:
我們使用seaborn庫中自帶的數據庫iris。如果沒有,需要在https://github.com/mwaskom/seaborn-data上下載。
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
data = pd.read_csv('iris.csv')
dataname = data['species']
print(data.head())
print('------------------')
freq = dataname.value_counts(normalize = True) #也可以不歸一化,在后面畫圖時候函數會自動歸一化
print(freq)
print('------------------')
colors = ['#81ecec','#ff7675','#6c5ce7']
plt.pie(freq, labels = freq.index, explode = (0.05, 0, 0), autopct = '%.1f%%', colors = colors, startangle = 90, counterclock = False)
plt.axis('square')
plt.legend(loc='upper right', bbox_to_anchor=(1.2, 0.2))
plt.show()
從圖表可以看出來,每一類的數據分布是均勻的。
接下來我們看iris中每一個特征分布圖,用柱狀圖表示。
如何生成隨機數據供我們學習,numpy可以生成各種分布的數據,下面用kdeplot()來繪圖,繪出數據的近似分布密度函數圖,如下:
代碼:
sns.set_style('ticks') sns.set_context('paper') x = np.random.uniform(0,1,10000) #均勻分布 y = np.random.normal(0,2,10000) # y ~ N(0,4) 正態分布 scale = 標准差S f = plt.figure() f.add_subplot(1,2,1)
#plt.title('x') sns.kdeplot(x) f.add_subplot(1,2,2)
#plt.title('y') sns.kdeplot(y) plt.show()
有了上面的練習,再來畫出iris數據各個特征的分布核函數:
sns.set_style('ticks') sns.set_context('paper') f = plt.figure(figsize=(8,6)) with sns.cubehelix_palette(8, gamma = 2): #gamma<1 unclear;gamma>1 clear f.add_subplot(2,2,1) sns.kdeplot(data['sepal_length']) f.add_subplot(2,2,2) sns.kdeplot(data['sepal_width']) f.add_subplot(2,2,3) sns.kdeplot(data['petal_length']) f.add_subplot(2, 2, 4) sns.kdeplot(data['petal_width']) plt.show()
我們再看不同類別的相同特征有什么樣的分布規律。
sns.set_context('paper') f = plt.figure(figsize=(8,6)) labels = dataname.drop_duplicates(inplace=False) labels = labels.reset_index(drop = True) featurename = data.columns print(featurename) for i in range(3): cls = data[dataname == labels[i]] cls.columns = labels[i]+'_'+featurename for j in range(4): f.add_subplot(2,2,j+1) plt.title(featurename[j]) sns.kdeplot(cls[labels[i]+'_'+featurename[j]]) plt.suptitle("kernel density estimations of the features of different irises")#中文顯示問題我還沒有解決,之后會出一隨筆寫有關plt中文顯示的問題 plt.show()
可以看出在petal_length和petal_width這兩個特征的密度分布函數圖中 setosa 和另外兩種iris區分很開,所以依據petal_length或者petal_width就足夠區分出是否為setosa了;
而另外兩種iris 4個特征的密度分布函數均有重疊,需要后序做進一步區分。
前面單單從一個維度(petal_lenght或者petal_width)足夠區分出一種花setosa, 對於另外兩種花我們期待能在高的維度上區分它們,所以
我們可以作出更高維度的圖看能否直觀的區分出它們。
from scipy.stats import pearsonr,norm sns.set_context('paper') data1 = data[data['species']=='versicolor'] data2 = data[data['species']=='virginica'] sns.jointplot(x = 'sepal_length', y = 'sepal_width', data = data1, marginal_kws=dict(bins = 20, kde = True, fit = norm, fit_kws = {'color': 'r'}, rug = True),stat_func = pearsonr, linewidth = 1, space = 0, color = 'b').set_axis_labels('versicolor_sepal_length','versicolor_sepal_width') plt.suptitle('versicolor\'s sepal feature') ax = sns.jointplot(data2['sepal_length'],data2['sepal_width'],marginal_kws=dict(bins = 20, kde = True, fit = norm, fit_kws = {'color': 'r'}, rug = True),stat_func = pearsonr, space = 0, color = 'g',kind = 'scatter') #kind = 'scatter', 'reg', 'resid', 'kde', 'hex' ax.plot_joint(sns.kdeplot, zorder = 0, n_levels = 6)#在前面一個圖的基礎上在加上核密度估計的聯合密度分布圖,通過plot_joint()實現。 plt.suptitle('virginica\'s sepal feature') plt.show()
從這兩個圖我們可以看出sepal_length和sepal_width有正相關關系,由於僅僅由一個sepal_length或者sepal_width,我們是無法區別這兩種花的,看了兩種花的sepal_length or width 分布后我們可以知道僅僅由這兩個數據我們依然無法區分sepal width, 左邊圖的中心在(6,2.5)左右,右邊圖的中心在(6.8,3)左右,兩中心距離較近,且可以看出feature向量分布很散。
現在需要將兩個圖合並為一個圖,這樣我們可以更清楚的判斷能否僅僅通過sepal數據來區分這兩種iris。
我們需要用到pairplot()函數:
''' seaborn.pairplot(data,hue = None,hue_order = None,palette = None,vars = None,x_vars = None,y_vars = None,kind =‘scatter’, diag_kind =‘auto’,markers = None,s = 2.5,aspect = 1,dropna = True,plot_kws = None,diag_kws = None,grid_kws = None) ''' sns.set_context('paper') new_data = data[data['species']!='setosa'] print(new_data.head()) new_data.reset_index(drop = True, inplace = True) print(new_data.head()) ax = sns.pairplot(new_data, kind = 'scatter', # 散點圖/回歸分布圖 {‘scatter’, ‘reg’} diag_kind="hist", # 設置對角線圖直方圖/密度圖 {‘hist’, ‘kde’} hue="species", # 按照某一字段進行分類 aspect = 1, #圖形比例1:1 palette="husl", # 設置調色板 markers=['o','x'], # 設置不同系列的點樣式(這里根據參考分類個數)'D','o','x','+'... size = 2, # 圖表大小 plot_kws={'size':2.5}, # 設置點大小 diag_kws={'edgecolor':'w'}) # 設置對角線直方圖樣式 plt.show()
可以看出當數據投影到二維平面上時候我們可以近似用一條直線將兩種iris花給區分開,
由(1,4),(2,4),(3,4)我們可以清晰的看見可以畫出一條分界線區分兩種花,
這說明了petal_width是區分這兩種花的關鍵。
sns.set_style('white',{'font.sans-serif':['simhei','Arial']}) sns.set_context('paper') new_data = data[data['species']!='setosa'] print(new_data.head()) new_data.reset_index(drop = True, inplace = True) print(new_data.head()) sns.pairplot(new_data, kind = 'reg', hue = 'species', markers = ['o','x'], diag_kind='kde',palette ='husl', diag_kws=dict(shade = True, color = 'g'), height = 2) plt.suptitle('對每一類兩個變量進行回歸分析圖表') plt.show()
前面添加一句話 sns.set_style('white',{'font.sans-serif':['simhei','Arial']})就可以顯示中文啦!
從圖表可以看出來不同種類的iris花各個特征之間的影響程度不同,petal_length對petal_width,不同種類影響也不同,
例如versicolor的petal_length對pental_width影響很大。