python matplotlib contour畫等高線圖

原文鏈接:https://blog.csdn.net/Mr_Cat123/article/details/80677525

函數畫圖

z=x2+y2z=x2+y2z=x2+y2z=x2+y2z=x2+y2 z=x^2+y^2z=x2+y2爲例

#導入模塊
import numpy as np
import matplotlib.pyplot as plt

#建立步長爲0.01,即每隔0.01取一個點
step = 0.01
x = np.arange(-10,10,step)
y = np.arange(-10,10,step)
#也可以用x = np.linspace(-10,10,100)表示從-10到10,分100份

#將原始數據變成網格數據形式
X,Y = np.meshgrid(x,y)
#寫入函數,z是大寫
Z = X**2+Y**2
#設置打開畫布大小,長10,寬6
#plt.figure(figsize=(10,6))
#填充顏色,f即filled
plt.contourf(X,Y,Z)
#畫等高線
plt.contour(X,Y,Z)
plt.show()

結果如下
這裏寫圖片描述
顏色越深表示值越小,中間的黑色表示z=0.
當然,也可以不要顏色填充,並只希望輸出z=20和z=40兩條線,則在上面代碼的基礎上,將plt.contourf去掉,並:

#只畫z=20和40的線,並將顏色設置爲黑色
contour = plt.contour(X,Y,Z,[20,40],colors='k')
#等高線上標明z(即高度)的值,字體大小是10,顏色分別是黑色和紅色
plt.clabel(contour,fontsize=10,colors=('k','r'))

結果如下:
這裏寫圖片描述
默認是保留3個小數,可以如下保留四位

plt.clabel(contour,fontsize=10,colors=('k','r'),fmt='%.4f')

以下,我將一些常用的功能補充全代碼,如下:

#導入模塊
import numpy as np
import matplotlib.pyplot as plt

#建立步長爲0.01,即每隔0.01取一個點
step = 0.01
x = np.arange(-10,10,step)
y = np.arange(-10,10,step)
#也可以用x = np.linspace(-10,10,100)表示從-10到10,分100份

#將原始數據變成網格數據形式
X,Y = np.meshgrid(x,y)
#寫入函數,z是大寫,這裏我讓中間的0是最大,加了一個負號
Z = -(X**2+Y**2)
#填充顏色,f即filled,6表示將三色分成三層,cmap那兒是放置顏色格式,hot表示熱溫圖(紅黃漸變)
#更多顏色圖參考:https://blog.csdn.net/mr_cat123/article/details/80709099
#顏色集,6層顏色,默認的情況不用寫顏色層數,
cset = plt.contourf(X,Y,Z,6,cmap=plt.cm.hot) 
#or cmap='hot'

#畫出8條線,並將顏色設置爲黑色
contour = plt.contour(X,Y,Z,8,colors='k')
#等高線上標明z(即高度)的值,字體大小是10,顏色分別是黑色和紅色
plt.clabel(contour,fontsize=10,colors='k')
#去掉座標軸刻度
#plt.xticks(())  
#plt.yticks(())  
#設置顏色條,(顯示在圖片右邊)
plt.colorbar(cset)
#顯示
plt.show()

這裏寫圖片描述
顏色取反

上面展示的是值越大越白,如果想要讓紅色在內,則只要在顏色名稱後加_r即可。其他顏色映射也是如此

cmap='hor_r'

數據畫圖

如果是已經有第三維(即高)的數據,那麼可以通過數據來畫圖
這裏先對mesh.grid作一個解釋:
mesh.grid可以將x,y軸變成數組(array),比如

這裏寫圖片描述
可以看到建立了一個二維平面,詳細見:meshgrid應用

比如有:

z = x**2 + y

而z是已經獲得的數據,那麼如何通過數據將z看成高呢?

import numpy as np
import matplotlib.pyplot as plt

z_list = []
for y in range(3):
    for x in range(3):
        z = x**2+y
        z_list.append(z)    #獲得z的數據
z = z_list    
x = np.linspace(0,2,3)
y = np.linspace(0,2,3)      
[X,Y] = np.meshgrid(x,y)   #生成X,Y畫布,X,Y都是3*3
#因爲z是一維,所以要變成3*3
z = np.mat(z)              
z = np.array(z)
z.shape = (3,3)
#畫圖(建議一定要查看X,Y,z是不是一一對應了)
plt.figure(figsize=(10,6))
plt.contourf(x,y,z)
plt.contour(x,y,z)

這裏寫圖片描述
這裏輸出X,Y和z如下,已經一一對應。
當x=0,y=0,則z=0
當x=0,y=1,則z=1
當x=0,y=2,則z=2


注意:我上面是用的先for y in xxx,再for x in xxx。
這裏寫圖片描述

另外,也可以輸出x,和y統一操作而不需要再寫,也不需要用meshgrid函數

x = np.linspace(xxx)

如下:

import numpy as np
import matplotlib.pyplot as plt

z_list = []
x_list = []
y_list = []
for x in range(3):
    for y in range(3):
        z = x**2+y
        z_list.append(z)
        x_list.append(x)
        y_list.append(y)
x,y,z = x_list,y_list,z_list
#對x操作
x = np.array(x)  #將list變成array
x.shape = (3,3)  #重新分成3*3的array
x = np.mat(x).T  #變成矩陣並轉置,因爲array沒有轉置 
#對y操作
y = np.array(y)   
y.shape = (3,3)
y = np.mat(y).T
#對z操作
z = np.array(z)
z.shape = (3,3)
z = np.mat(z).T
#畫圖
plt.figure(figsize=(6,4))
plt.contourf(x,y,z)
plt.contour(x,y,z)

這裏寫圖片描述
這裏寫圖片描述

選擇性畫圖

如果我只想畫出等高線某些部分的線,比如想畫高爲0.00221,和0.00223的線,那麼可以使用下面命令

contour = plt.contour(X,Y,Z,[0.00221,0.00223],colors='k')

在這裏插入圖片描述
———————————————————我是會賣萌的分割線————————————————————
以下是我的筆記,大家可以選擇不看。

例一

已知x+y+z=163,f=f(x,y,z)找出x,y,z對於的值使得f最大
分析:由x+y+z=163可知是有一條線分開,即z=163-x-y,帶入f中消掉z,然後再用一個個賦值x,y循環得到f的值,最後採用max挑出f最大的值
由於這裏是有四個變量,x,y,z,和f,而x+y+z=163,需要做的是畫出橫座標爲x,縱座標爲y,高爲f的等高線圖,跟上面的例子已經不同,上面的例子只有三個變量,x,y,和z,畫出x爲橫座標,y爲縱座標,z爲高的圖,所以兩者是不同的。不同導致的區別如:
上面的例子得到的x是:

[0, 0, 0, 1, 1, 1, 2, 2, 2]

而下面將講的得到的x類似是

[0,0,0,1,1,2]

所以需要將缺省的一個1和兩個2的位置補上0,同理y和f也是
這裏爲了快速和簡單,只要補充f(下面用z代替了)即可,而x,y可以重新用range生成
注意:這裏的z跟代碼中的z不同,代碼中的z是f的值

#導入模塊
import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate
from matplotlib import colors

an = []
i = 0
tot = 163
z = np.loadtxt(r'/home/wudl/myfiles/LSPE/data/f90_140_220/FoM1.txt')#加載數據(只加載z座標這一列)
#生成橫縱座標,並且將橫縱座標對應的點z的值放到空列表an中
for x in range(1,162,1):
    for y in range(1,162,1):
        if x+y >= 163:
            an.append(0)
        else:
            an.append(z[i])
            i += 1
        
x = np.arange(1,tot-1,1)
y = np.arange(1,tot-1,1)

X,Y = np.meshgrid(x,y)
Z = np.mat(an)
Z.shape = (tot-2,tot-2)
Z = Z.T
#自定義顏色條
colorslist = ['w','gray','aqua']
#將顏色條命名爲mylist,一共插值顏色條3000個
cmaps = colors.LinearSegmentedColormap.from_list('mylist',colorslist,N=3000)
#畫40層顏色
cset = plt.contourf(X,Y,Z,40,cmap = cmaps)
#畫200條線,設置字體大小爲10
contour = plt.contour(X,Y,Z,200,colors='k')
plt.clabel(contour,fontsize=10,colors='k')
#座標軸的字體採用LATEX
plt.xlabel('$n_{90}$',fontsize=20)
plt.ylabel('$n_{220}$',fontsize=20)
#顯示顏色條
plt.colorbar(cset)
#顯示圖片
plt.show()

例二

from __future__ import division
import os
os.chdir('/media/sf_Share/fisher_matrix/myLSPE/LSPE4')  #ATTENTION:change work dir
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
import settings
from matplotlib import colors

st = settings.Settings()

data = np.loadtxt(r'/media/sf_Share/fisher_matrix/myLSPE/data/fsky0.7/41+95+150/r_0.01/sigma_F_0.1/sigma_F=0.1/threefre.txt')

#data = np.loadtxt(r'/media/sf_Share/fisher_matrix/myLSPE/data/threefre.txt')
z = data[:,3]   #sigma_r
zmin = min(z)
print(zmin)
an = []
i = 0
for x in range(1,st.tot_det-1,st.step):     #x_min=1,x_max=161
    for y in range(1,st.tot_det-1,st.step):
        if x+y >= st.tot_det:
            an.append(0)
        else:
            an.append(z[i])
            i += 1

x = np.arange(1,st.tot_det-1,st.step)
y = np.arange(1,st.tot_det-1,st.step)
X,Y = np.meshgrid(x,y)
Z = np.mat(an)
Z.shape = (X.shape[0],X.shape[0])
Z = Z.T

colorslist = ['w','gainsboro','gray','aqua']
#將顏色條命名爲mylist,一共插值顏色條50個
cmaps = colors.LinearSegmentedColormap.from_list('mylist',colorslist,N=200)
#cmaps = mpl.cm.hot
#自定義顏色範圍,
norm = colors.Normalize(vmin=0.0017,vmax=0.0040)
#cset = plt.contourf(X,Y,Z,100,cmap = 'BuGn') 
cset = plt.contourf(X,Y,Z,100,alpha=1,vmin=0.0017,vmax=0.0040,cmap = 'hot_r')
contour = plt.contour(X,Y,Z,[0.00210,0.00220,0.00230,0.00240,0.00250,0.00260,0.00270,0.00280],colors='k')
plt.clabel(contour,fontsize=10,colors='k',fmt='%.5f')
plt.scatter(2901,6101,color='r')
plt.axis([0,10000,0,10000])
plt.colorbar(cset)
#plt.xlabel(str(st.nu[0])+ ' frequency')
#plt.ylabel(str(st.nu[1])+' frequency')
plt.xlabel('$N_{41}$')
plt.ylabel('$N_{95}$')
plt.show()

在這裏插入圖片描述

另:

contour這個函數主要對網格中每個點的值等於一系列值的時候做出一條條輪廓線,類似於等高線 。

contour([X, Y,] Z, [levels], ** kwargs)
繪製輪廓。

  • 參數:
    • X,Y : array-like,可選
      值Z的座標。
      X和Y必須都是2-D,且形狀與Z相同,或者它們必須都是1-d,這樣len(X)== M是Z中的列數,len(Y)== N是Z中的行數。
    • Z : array-like(N,M)
      繪製輪廓的高度值。
    • levels: int或類似數組,可選
      確定輪廓線/區域的數量和位置。
      如果int Ñ,使用Ñ數據間隔; 即繪製n + 1個等高線。水平高度自動選擇。
      如果是數組,則在指定的級別繪製輪廓線。值必須按遞增順序排列。
  • 返回:
    c : QuadContourSet
  • 其他參數:
    詳見: https://matplotlib.org/api/_as_gen/matplotlib.pyplot.contour.html#matplotlib.pyplot.contour

下面用代碼展示這個函數的效果

import numpy as np
import matplotlib.pyplot as plt

delta = 0.25  #網格間距
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-3.0, 3.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (Z1 - Z2) * 2
fig, ax = plt.subplots()
CS = ax.contour(X, Y, Z)
ax.clabel(CS, inline=1, fontsize=10)
plt.show()

在這裏插入圖片描述
我們也可以使網格更緊密些,如設置delta=0.025
在這裏插入圖片描述
嘗試修改參數,如顏色,線型,“等高線”,再來看下效果

CS = ax.contour(X, Y, Z ,colors=['k', 'k', 'k','r','r'], linestyles=['--','--', '-', '--','--'],
                levels=[-1,-.5, 0, .5,1])

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章