如何用python繪製溫度分布圖(matplotlib繪圖)

如何用python繪製溫度分布圖(matplotlib繪圖)

一.前言

以前在研究所,在處理一個2D空間的溫度分布情形時,我總是會用Origin來做溫度分布圖,我找了Origin官網的文章來說明

(參考網站: Origin官網的文章 )
附圖是該網站的範例圖面,可以很清楚看到,整個北美洲的溫度分布情形。
再由溫度的Scale Bar來判讀,大概靠近底部的地方,溫度會是在60度左右,靠近北方則是10~20度之間。
這很清楚的表達該區域的溫度分布。

近期我在工作上碰到一個問題,我有一個X-Y位置及其對應的溫度值的資料,當時我在excel找了老半天,都無法像Origin那樣做出一個2D平面的溫度分布圖。
接著我就想,除了Origin之外,能否也可以用Python來繪製溫度分布圖呢?

二.簡單的繪製分布圖

首先,這種”分布圖”,在Origin叫做”contour”,剛好Python裡的matplotlib也有contour的指令,起初在網路上找關於此類文章,例如:
1.怎么用Python画这种温度分布图
2.Python Matplotlib Tips
3.绘制轴线或Matplotlib轮廓图的原点
4.matplotlib.pyplot contourf()函式的使用
很可惜的是,他們的該點資料都是X和Y的函數,ex: Z= X+Y*2 這個意思。
這樣子根本無法達到我的”輸入某個位置的資料”的概念,因為該點的溫度值不可能可以構成X和Y的函數麻。

上述這幾個網站的方法是這樣子的,將X和Y個切成很細的位子點,接著將Z令成X和Y的函數,這樣子就有超多的位子點資料。然後將它plot出來。
我的應用則可能只知道某9個點的溫度值而已,要怎麼把9個點溫度值給切碎分給X和Y呢?

後來真的是我想太多了,如果點資料不夠多,那就不要把X和Y切細阿。廢話不多說,馬上看我寫的程式碼。

#舉例 僅有3*3的位置點資料
import matplotlib.pyplot as plt
x = [0,2,3] #X位置
y = [0,3,6] #Y位置
temp = [[5,15,30],[10,20,50],[20,30,40]] #該點資料

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)   #生成Scale bar
c = ax.contourf(x, y, temp,cmap='Spectral_r')
cb = fig.colorbar(c)
cb.set_label('Temperature')
plt.xlabel('position(mm)')
plt.ylabel('position(mm)')
plt.show()

輸出結果:

看看是不是非常簡單,短短的程式碼就可以畫出輪廓圖囉。

三.讀取CSV檔案繪製溫度分布圖

假設我有一個CSV檔案,數據資料如下

0	0	10
0	3	20
0	6	40
2	0	15
2	3	20
2	6	55
3	0	20
3	3	30
3	6	45

第一行表示X位置、第二行是Y位置、第三行則是溫度
那我如何從這CSV讀取資料然後繪製溫度分布圖呢?程式碼如下:

#讀取CSV繪製溫度分布圖
#注意!必須是個X*Y的矩陣資料才可以
import matplotlib.pyplot as plt
import csv

with open('data.csv',encoding="utf-8-sig") as csvFile: #CSV讀取
    csvReader = csv.reader(csvFile)
    x,y,z,a,b,c=[],[],[],[],[],[]
    for row in csvReader:
        if not a is row[0]:
            x.append(row[0])
            c.append(z)
            z=[]
        if not row[1] in y: 
            y.append(row[1])
        z.append(row[2])
        a=row[0]
        b=row[1]
    del c[0]
    c.append(z)

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)   #生成Scale bar
c = ax.contourf(x, y, c,cmap='Spectral_r')
cb = fig.colorbar(c)
cb.set_label('Temperature')
plt.xlabel('position(mm)')
plt.ylabel('position(mm)')
plt.show()

輸出結果:

是不是很簡單呢!不過這裡有些限制,點資料必須是個X*Y的矩陣。

2 comments Add yours
  1. 您好,我使用”三.讀取CSV檔案繪製溫度分布圖”裡面的語法但輸入我自己較多行(3*43萬)的數據但失敗了,為什麼呢?

    我也沒有看懂您打開CSV後的內容,可以為我解釋一下嗎?謝謝.

    1. 李 您好:
      抱歉這麼久才回覆,其實我自己有一段時間沒碰程式了,又再花一點時間重溫一下。
      針對你的問題,我自己測試更多筆數據時,發現此程式碼有些限制:
      1.數據必須要是方陣矩陣
      意思是x=[0,2,3] y=[0,3,6] 時可以
      但是x=[0,2,3] y=[0,3,6,8] 會plot失敗,原因為matplotlib.pyplot的限制。

      可解決的辦法是將x和y兩個數值的數量要相同,但有可能情況是,假設x=10時,剛好y=10沒有數據,這時看看是否用內插法,把(10,10)時Z值給求出來。

      2. 第一列x要依照數字大小排列
      因為程式碼的
      "if not a is row[0]:
      x.append(row[0])
      c.append(z)
      z=[] ”
      是將z值丟到c這個集合裡,並將z=[]

      所以假設您的data長這樣時:
      0 0 10
      2 0 20
      3 0 30
      0 1 40
      2 1 50
      3 1 60
      會發生錯誤,應要排列成:
      0 0 10
      0 1 40
      2 0 20
      2 1 50
      3 0 30
      3 1 60

      第二個問題是

      with open(‘data.csv’,encoding=”utf-8-sig”) as csvFile: #CSV讀取
      csvReader = csv.reader(csvFile)
      x,y,z,a,b,c=[],[],[],[],[],[]
      for row in csvReader:
      if not a is row[0]: #當a值不等於當前第一列的值時
      x.append(row[0]) #x集合加入第一列的值
      c.append(z) #將z集合丟到c集合裡 (c會是是個充滿集合的集合)
      z=[] #z=[],重置
      if not row[1] in y: #當第二列數值沒有在y集合裡時
      y.append(row[1]) #y集合加入第二列的值
      z.append(row[2]) #z集合新增第三列的值
      a=row[0] #將a=第一列的值
      b=row[1] #將b=第二列的值
      del c[0] #將c[0]時空集合給刪掉
      c.append(z) #將最後一個z集合給c集合

      這樣有了解嗎?

      謝謝!

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *