Python繪圖總結(seaborn庫的使用)(下)


上部分介紹了pie以及kdeplot、distplot、jointplot、pairplot的用法分別繪制出數據的餅圖、核密度分布圖、

柱狀圖、散點圖、以及用jointplot繪制組合圖。

下面開始總結(散點圖(二維,三維),折線圖,(並列,疊加)柱狀圖,三維曲面圖,箱線圖的畫法):
(一)散點圖:(relplot, scatterplot)

'''
seaborn.relplot(x=None, y=None, hue=None, size=None, style=None, data=None, row=None, col=None, col_wrap=None, row_order=None, col_order=None, palette=None, hue_order=None, hue_norm=None, sizes=None, size_order=None, size_norm=None, markers=None, dashes=None, style_order=None, legend='brief', kind='scatter', height=5, aspect=1, facet_kws=None, **kwargs)
'''
# -*- coding: utf-8 -*-
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
from scipy.stats import pearsonr,norm
data = pd.read_csv('anscombe.csv')
print(data.head())
sns.set_context('paper')
sns.set_style('ticks',{'font.sans-serif':['simhei','Arial']})
pal = sns.husl_palette(n_colors=4,l = .7)
sns.relplot(x = 'x', y = 'y', data = data, hue = 'dataset',style = 'dataset',sizes = (100,100),palette = pal)
plt.suptitle("不同組的x與y之間的關系")
plt.show()

 不同組相同style,都是圓形; 

不同組不同style。

顯然我們的目的不僅僅是觀察散點分布,更重要的是為了尋求x與y之間以及不同組之間的關系。

我們對每一組的(x,y)連起來形成一個折線圖,僅僅需要將kind = 'scatter'(默認)改為 kind = 'line';

可得圖:

可以看出第二組數據點形成的曲線近似於拋物線軌跡,第四組數據點都在直線上(垂直於x的直線,說明y與x無關,因為有一個點偏離較遠所以導致折線圖出現這種情況),而第一組和第三組,線性不是很明顯,但是這兩組y與x呈明顯的正相關關系。

現在我們需要對這幾組數據用回歸擬合,找出每組內x與y之間的函數關系。

from scipy.stats import linregress
data = pd.read_csv('anscombe.csv')
print(data.head())
sns.set_context('paper')
sns.set_style('ticks',{'font.sans-serif':['simhei','Arial']})
cls = ['I','II','III','IV']
markers = ['o','x','^','*']
c = ['r','b','g','y']
data = data[data['x']<18] #刪除異常值,因為我們知道百分之95的數據的x都在(4,18)區間內,離群點對線性回歸影響很大,特別是當數據量較小的時候
f = plt.figure(figsize=(8,6))
for i in range(4):
    dt = data[data['dataset']==cls[i]]
    k,b,r,p,std = linregress(dt['x'],dt['y'])
    flag = 1
    if np.isnan(k):
        k,b,r,p,std= linregress(dt['y'],dt['x'])
        flag = 0
    plt.scatter(dt['x'],dt['y'],marker=markers[i],label = cls[i])
    if flag:
        plt.plot(dt['x'],k*dt['x']+b,color = c[i],label = cls[i])
    else:
        plt.plot(k*dt['y']+b,dt['y'],color = c[i],label = cls[i])
        flag = 1
plt.legend(loc = 'upper left')
plt.suptitle('線性擬合各組數據')
plt.show()

 

 

箱線圖:

我們可以根據box圖或者violin圖來看每一組數據分布的區間,可以方便我們判斷離群點:

data = pd.read_csv('anscombe.csv')
print(data.head())
sns.set_context('paper')
sns.set_style('ticks',{'font.sans-serif':['simhei','Arial']})
f = plt.figure(figsize=(8,6))
f.add_subplot(221)
sns.boxplot('dataset','x',data = data, palette = 'husl')
plt.xlabel('(a)')
f.add_subplot(222)
sns.boxplot('dataset','y',data = data, palette='husl')
plt.xlabel('(b)')
f.add_subplot(223)
sns.violinplot('dataset','x',data = data, palette = 'husl')
plt.xlabel('(c)')
f.add_subplot(224)
sns.violinplot('dataset','y',data = data, palette = 'husl')
plt.xlabel('(d)')
plt.tight_layout()
plt.show()

 

由圖(c)可以看出第IV組的大部分的數據的x集中在8一點,而y分布與6周圍,可以知道y和x的相關性很小,通過(a) (b)我們也可以看到離群點,

(a)至少有一個離群點,分布在x>18范圍內,(b)至少有里兩個離群點,分布在y>12范圍內。

我們可以根據這個來刪掉離群點,使得擬合結果更可信。

 三維散點圖:

先看三維曲線圖

import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt

mpl.rcParams['legend.fontsize'] = 10
fig = plt.figure()
ax = fig.gca(projection='3d')
theta = np.linspace(-4 * np.pi, 4 * np.pi, 100) #變量theta,決定(x,y,z),所以形成的圖形為三維空間中的一維曲線(z與theta是呈線性關系的,繪出100個點。
z = np.linspace(-2, 2, 100)
r = z ** 2 + 1
x = r * np.sin(theta)
y = r * np.cos(theta)
ax.plot(x, y, z, label='curve',color = 'g')
ax.legend()
plt.show()

再看三維散點圖

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
plt.rcParams['font.family'] = ['Arial Unicode MS']  # 用來正常顯示中文標簽
plt.rcParams['axes.unicode_minus'] = False  # 用來正常顯示負號
sns.set_style('whitegrid', {'font.sans-serif': ['Arial Unicode MS', 'Arial']})
#用來解決中文方塊化的問題

x = np.random.normal(0,2,size = (3,50))
y = np.random.normal(4,2,size = (3,50))
fig = plt.figure(figsize=(10,5))
ax1 = fig.add_subplot(121, projection='3d')
ax1.scatter(x[0],x[1],x[2],color = 'r',marker = 'o',label = '紅點')
ax1.scatter(y[0],y[1],y[2],color = 'b',marker = '^',label = '藍點')
ax1.legend()
ax1.set_xlabel('X')
ax1.set_ylabel('Y')
ax1.set_zlabel('Z')
ax2 = fig.add_subplot(122,projection='3d')
ax2.scatter(x[0],x[1],x[2],color = 'r',marker = 'o',label = '紅點')
ax2.scatter(y[0],y[1],y[2],color = 'b',marker = '^',label = '藍點')
x1 = np.linspace(-5,5,100)
y1 = np.linspace(-3,8,100)
x1,y1 = np.meshgrid(x1,y1)
z1 = 6*np.ones(shape = (100,100)) - x1 - y1
ax2.plot_surface(x1,y1,z1,cmap=cm.coolwarm,
            rstride=1, # rstride(row)指定行的跨度
            cstride=1, # 列跨度
            linewidth = 0, #線寬最低
            antialiased = True) #抗鋸齒打開
ax2.legend()
ax2.set_xlabel('X')
ax2.set_ylabel('Y')
ax2.set_zlabel('Z')
plt.show()

可以看出x + y + z = 6的平面剛好能夠把紅點和藍點區分開。

因為紅點呈中心為原點的正態分布,藍點呈中心為(4,4,4)的正態分布,

x+y+z = 6剛好是過兩個中心中點的垂直平面,可以將兩個正態分布的散點區分開。

接下來我們要繪制x^2 - y^2 = z的圖像 (馬鞍面)

三維曲面圖: 

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
plt.rcParams['font.family'] = ['Arial Unicode MS']  # 用來正常顯示中文標簽
plt.rcParams['axes.unicode_minus'] = False  # 用來正常顯示負號
sns.set_style('whitegrid', {'font.sans-serif': ['Arial Unicode MS', 'Arial']})
#用來解決中文方塊化的問題
x = np.linspace(-5,5,100)
y = np.linspace(-5,5,100)
x,y = np.meshgrid(x,y)
z = x**2-y**2
f = plt.figure(figsize=(5,4))
ax = f.add_subplot(111,projection = '3d')
ax.plot_surface(x, y, z, cmap=plt.get_cmap('rainbow'), rstride = 4,cstride = 4,
                       linewidth=0, antialiased=False)
ax.set_zlim(-20, 20)
ax.zaxis.set_major_locator(LinearLocator(11)) #z方向上均勻分成11-1=10份,即找11個分點,
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f')) #分節點的值保留兩位小數
plt.show()

可以看出來當行跨度、列跨度為4的時候,划分曲線顯得十分明顯,使得整個曲面呈網格狀。

另外我們能在plt.show()前面加上 f.colorbar(surf, shrink=.5, aspect=5)  #shrink越小,表示colorbar越小

便可以在右邊繪制一個colorbar:

我們從圖中也可以看出相近的顏色的點高度都是相同的,我們能否直接繪制等高線呢?

當然可以!

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
plt.rcParams['font.family'] = ['Arial Unicode MS']  # 用來正常顯示中文標簽
plt.rcParams['axes.unicode_minus'] = False  # 用來正常顯示負號
sns.set_style('whitegrid', {'font.sans-serif': ['Arial Unicode MS', 'Arial']})
#用來解決中文方塊化的問題
x = np.linspace(-5,5,100)
y = np.linspace(-5,5,100)
x,y = np.meshgrid(x,y)
z = x**2-y**2
f = plt.figure(figsize=(5,4))
ax = f.add_subplot(111,projection = '3d')
surf = ax.plot_surface(x, y, z, cmap=cm.coolwarm, rstride = 4,cstride = 4,
                       linewidth=0, antialiased=False)
cset = ax.contour(x, y, z, zdir = 'z',offset = 30, cmap=cm.coolwarm, antialiased=False)
ax.set_zlim(-20, 20)
ax.zaxis.set_major_locator(LinearLocator(11)) #z方向上均勻分成11-1=10份,即找11個分點,
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f')) #分節點的值保留兩位小數
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
f.colorbar(surf, shrink=.5,aspect = 5)
plt.show()

疊加柱狀圖(用處較大):

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = ['Arial Unicode MS']  # 用來正常顯示中文標簽
plt.rcParams['axes.unicode_minus'] = False  # 用來正常顯示負號
sns.set_style('ticks', {'font.sans-serif': ['Arial Unicode MS', 'Arial']}) #用來解決中文方塊化的問題

N = 13 #含有13組數據 每一組又分為三類A B C,每一類的頻數記錄其中
A = (52, 49, 48, 47, 44, 43, 41, 41, 40, 38, 36, 31, 29)
B = (38, 40, 45, 42, 48, 51, 53, 54, 57, 59, 57, 64, 62)
d = []
for i in range(0, len(A)):
    sum = A[i] + B[i]
    d.append(sum)
C = (10, 11, 7, 11, 8, 6, 6, 5, 3, 3, 7, 5, 9)
ind = np.arange(N)  #ind表示橫軸坐標
width = 0.4 #條形寬度設為0.4

p1 = plt.bar(ind, A, width, color = '#636e72')
p2 = plt.bar(ind, B, width, bottom=A, color = '#0984e3')
p3 = plt.bar(ind, C, width, bottom=d, color = '#fdcb6e') #最上面一層應該是前面那個相加得到的d作為下限

plt.ylabel('頻數')
plt.title('不同組別各類數目分布')
plt.xticks(ind, ('G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7', 'G8', 'G9', 'G10', 'G11', 'G12', 'G13'))
plt.yticks(np.arange(0, 81, 20))
plt.legend((p1[0], p2[0], p3[0]), ('A', 'B', 'C'), loc = 'upper right', bbox_to_anchor = (1.13,1.02)) #用兩個元組表示legend標簽,p[0]表示該圖所擁有的顏色
plt.show()

可以看出B類別在每個組都比較多,而A類別在每個組都比較少。

綜上就是Python繪圖主要用的一些函數及其實例,后面會更新一些有關機器學習算法的總結,大家一起學習,一起進步~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM