matplotlib---8.3D繪圖


一、直線、散點圖、插值

1.3D繪圖與2D繪圖區別

3D繪圖與2D繪圖的調用方法幾乎相同,除了增加一個 projection='3d'的關鍵字參數。

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig=plt.figure()
ax=fig.add_subplot(111,projection='3d') # 舊式寫法
ax=Axes3D(fig) #新式寫法

2.插值畫3D圖

(1)載入數據

# 載入模塊
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import pandas as pd
import seaborn as sns
from scipy import interpolate

df_epsilon_alpha = pd.read_excel('實驗記錄_超參數.xlsx',sheet_name='epsilon_alpha')
#生成數據
epsilon = np.array(df_epsilon_alpha['epsilon'].values)
alpha = np.array(df_epsilon_alpha['alpha'].values)
Precision = np.array(df_epsilon_alpha['Precision'].values) 

(2)將x和y擴充到想要的大小

xnew = np.arange(0.1, 1, 0.09) #左閉右閉每0.09間隔生成一個數
ynew = np.arange(0.1, 1, 0.09)  
或者
x = np.linspace(0.1,0.9,9)#0.1到0.9生成9個數
y = np.linspace(0.1,0.9,9)

(3)對z插值

x,y原數據:

x = np.linspace(0.1,0.9,9)
y = np.linspace(0.1,0.9,9)
z = Precision

采用 scipy.interpolate.interp2d函數進行插值

f = interpolate.interp2d(x, y, z, kind='cubic')

x,y擴充數據:

xnew = np.arange(0.1, 1, 0.03)#(31,)
ynew = np.arange(0.1, 1, 0.03)#(31,)
znew = f(xnew, ynew)#(31,31) 

znew為插值后的z

(4)畫圖

采用  from mpl_toolkits.mplot3d import Axes3D進行畫三維圖

Axes3D簡單用法:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

比如采用plot_trisurf畫三維圖:

plot_trisurf(x,y,z)

plot_trisurf對數據要求是:x.shape = y.shape = z.shape,所以x和y的shape需要修改,采用np.meshgrid,且都為一維數據

修改x,y,z輸入畫圖函數前的shape

xx1, yy1 = np.meshgrid(xnew, ynew)#執行之后,xx1.shape=(31,31),yy1.shape=(31,31)
newshape = (xx1.shape[0])*(xx1.shape[0])
y_input = xx1.reshape(newshape)
x_input = yy1.reshape(newshape)
z_input = znew.reshape(newshape)

x_input.shape,y_input.shape,z_input.shape=((961,), (961,), (961,))

#畫圖
sns.set(style='ticks')
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(x_input,y_input,z_input,cmap=cm.coolwarm)

plt.xlim((0.1,0.9))
plt.xticks([0.1,0.3,0.5,0.7,0.9])
plt.yticks([0.1,0.3,0.5,0.7,0.9])
ax.set_xlabel(r'$\alpha$',fontdict={'color': 'black',
                             'family': 'Times New Roman',
                             'weight': 'normal',
                             'size': 18})
ax.set_ylabel(r'$\epsilon$',fontdict={'color': 'black',
                             'family': 'Times New Roman',
                             'weight': 'normal',
                             'size': 18})
ax.set_zlabel('precision',fontdict={'color': 'black',
                             'family': 'Times New Roman',
                             'weight': 'normal',
                             'size': 18})

plt.tight_layout()
# plt.savefig('loc_svg/alpha_epsilon2.svg',dpi=600) #指定分辨率保存
plt.show()
插值前 插值后
 

3.繪制直線

Axes3D.plot(xs, ys, *args, **kwargs)

參數: 

  1. xs,ys點的 x,y坐標
  2. zs點的z坐標。該值可以是一個標量(表示對所有點都取同一個值);也可以是個數組或列表,表示每個點一個值
  3. zdir指定那個是z軸。其值可以是'x'或者'y'或者'z'
  4. 剩下的關鍵字參數與Axes.plot()相同

4.繪制散點圖

Axes3D.scatter(xs, ys, zs=0, zdir=’z’, s=20, c=’b’, depthshade=True, *args, **kwargs)

參數:

  1. xs,ys點的 x,y坐標
  2. zs點的z坐標。該值可以是一個標量(表示對所有點都取同一個值);也可以是個數組或列表,表示每個點一個值
  3. zdir指定那個是z軸。其值可以是'x'或者'y'或者'z'
  4. s散點的大小(單位為 point^2).該值可以是一個標量(表示對所有點都取同一個值);也可以是個數組或列表,表示每個點一個值
  5. c散點的顏色。你可以將它設為一個顏色字符串,表示所有的點都是一個顏色。或者是個 cmap,指定顏色圖
  6. depthshade一個布爾值。如果為True,則通過對marker設置陰影來展示層次關系
  7. 剩下的關鍵字參數與Axes.scatter()相同

5.繪制線框 

Axes3D.plot_wireframe(X, Y, Z, *args, **kwargs)

參數:

  • X,Y點的 x,y坐標
  • Z點的z坐標。該值可以是一個標量(表示對所有點都取同一個值);也可以是個數組或列表,表示每個點一個值
  • rstride行的步長
  • cstride列的步長
  • 剩下的關鍵字傳遞給LineCollection

二、修改X,Y,Z軸的刻度值

1.修改X,Y,Z軸的刻度值

from matplotlib.ticker import MultipleLocator,FuncFormatter
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib import colors
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
import matplotlib.ticker as ticker

def fun(x):
    if x >= 1:
        return 1
    return x

def to_percent(temp, position):
    return '%1.0f'%(100*temp)

x = np.arange(0, 0.5, 0.001)
y = np.arange(0, 0.05, 0.001)
x, y = np.meshgrid(x, y)
z = (3*x+y-x*x-np.sqrt(2*x*x*x-3*x*x*x*x+x*x+22*x*x*y-22*x*y-12*x*x*x*y-8*x*x*y*y+12*x*y*y-7*y*y))/(2*x+2*y)

for row in range(len(z)):
    for col in range(len(z[0])):
        z[row][col] = fun(z[row][col])

fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_zlim3d(0.6,1.0)
ax.zaxis.set_major_locator(LinearLocator(5))#Z軸顯示5個刻度值

norm = colors.Normalize(vmin=0.6,vmax=1.0)
ax.xaxis.set_major_formatter(FuncFormatter(to_percent))#將X,Y,Z軸的坐標軸放大100倍
ax.yaxis.set_major_formatter(FuncFormatter(to_percent))
ax.zaxis.set_major_formatter(FuncFormatter(to_percent))

ax.set_xlabel(r'$\alpha$(%)')
ax.set_ylabel(r'$\theta$(%)')
ax.set_zlabel(r'$\gamma^{*}$(%)')#坐標軸

surf = ax.plot_surface(x, y, z,
                       cmap=cm.coolwarm,
                       linewidth=0,
                       norm=norm,
                       antialiased=False,
                       edgecolor='none')
ax.contourf(x,y,z,zdir='z',offset=-2,cmap='rainbow')

修改colorbar的刻度為百分的形式

def fmt(x,pos):
    print(x)
    # a, b = '{:2.2e}'.format(x).split('e')
    # b = int(b)
    return r'${}$%'.format(int(x*100))
cbar = plt.colorbar(surf,shrink=0.5, aspect=5,format=ticker.FuncFormatter(fmt))#format用來修改調色板的刻度值
cbar.set_ticks([.6,.7,.8,.9,1.0]) plt.tight_layout() 
plt.savefig('實驗圖.svg',dpi=600) #指定分辨率保存 
plt.show()  
未修改前 修改后
 

alpha:0.0-0.5

theta:0.00-0.05

gamma:0.60-1.00

colorbar:0.60-1.00

alpha:0:50(每個乘以100)

theta:0-5(每個乘以100)

gamma:60-100(每個乘以100)

colorbar:60%-100%(每個乘以100)

 

 

 

 

參考文獻:

【1】matplotlib 修改坐標軸刻度值,刻度個數

【2】解決python畫圖中colorbar設置刻度和標簽字體大小

【3】Matplotlib:給子圖添加colorbar(顏色條或漸變色條)


免責聲明!

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



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