Python 畫極坐標圖


需要用Python畫極坐標等值線圖,以下是所學的一些東西,特此記錄

--------------------------------------------------

翻譯自 https://stackoverflow.com/questions/9071084/polar-contour-plot-in-matplotlib-best-modern-way-to-do-it

你應該能夠像往常一樣使用極地圖的ax.contour或ax.contourf 。單位是弧度,傳遞函數的順序是,theta,r

import numpy as np
import matplotlib.pyplot as plt

#-- Generate Data -----------------------------------------
# Using linspace so that the endpoint of 360 is included...
azimuths = np.radians(np.linspace(0, 360, 20))
zeniths = np.arange(0, 70, 10)

r, theta = np.meshgrid(zeniths, azimuths)
values = np.random.random((azimuths.size, zeniths.size))

#-- Plot... ------------------------------------------------
fig, ax = plt.subplots(subplot_kw=dict(projection='polar'))
ax.contourf(theta, r, values)

plt.show()

結果

 

翻譯自http://blog.rtwilson.com/producing-polar-contour-plots-with-matplotlib/

創建一些極坐標軸,在上面繪制輪廓圖:

fig, ax = subplots(subplot_kw = dict (projection = 'polar' ))
cax = ax.contourf(theta, r, values, nlevels)

這個利用了contourf函數,產生了一個填充的輪廓圖,使用輪廓函數可以得到簡單的輪廓線。這個函數的前三個參數必須被被給定,它們都是二維數組,包含:半徑raddi,角度(theta)和輪廓的實際值。最后一個參數是要繪制的輪廓的層次數——如果希望得到等值線圖,則數字可以小一些,如果希望得到填充的等值線圖,則數字需要大一些(以獲得平滑的外觀)。(如果希望最外面的輪廓足夠圓,則需要網格點足夠密集)

我從來沒有完全理解這些二維數組,以及為什么需要它們。我通常以三個列表的形式獲得我的數據,這些列表基本上是表的列,其中表的每一行都定義了一個點和值。例如:

Radius   Theta    Value 10      0       0.7
10      90      0.45
10      180        0.9
10       270       0.23
20       0         0.5
20       90        0.13
20       180       0.52
20        270       0.98

  這些行中的每一行都定義一個點 - 例如,第一行定義半徑為10的點,角度為0度,值為0.7。我永遠無法理解為什么輪廓功能不只是采用這三個列表並繪制一個等高線圖。事實上,我已經編寫了一個函數來完成這個,我將在下面描述,但首先讓我解釋一下這些值是如何轉換為二維數組的。

首先,讓我們想一想維數:我們的數據中顯然有維數,半徑和角度。事實上,我們可以重新塑造我們的數值數組,使得它變成二維的。我們可以從上表中看到,我們正在做半徑為10度的所有方位角,然后是半徑為20度的相同方位角,等等。因此,我們的值不是存儲在一維列表中,我們可以把它們放在一個二維表中,其中列是方位角,行是半徑:

 0 90 180 270 10    0.7    0.45    0.9    0.23
20    0.5    0.13    0.52    0.98

 這正是我們需要為contourf函數賦予的那種二維數組。這並不難理解——但為什么地球上的半徑和角度數組也必須是二維的。好吧,基本上我們只需要兩個像上面那樣的數組,但是在對應的單元格中有相應的半徑和角度,而不是值。所以,對於角度,我們有:

 0 90 180 270
10    0    90    180    270
20    0    90    180    270

對於半徑,我們有:

 0 90 180 270
10    10   10    10    10
20    0    20    20    20

 

然后,當我們將所有三個數組放在一起時,每個單元格將定義我們需要的三個信息。因此,左上角的單元格給出的角度為0,半徑為10,值為0.7。幸運的是,你不必手動制作這些數組——一個名為meshgrid的方便的NumPy函數會為你做:

>>> radii = np.arange(0, 60, 10)
>>> print(radii)
[ 0 10 20 30 40 50]
>>> angles = np.arange(0, 360, 90)
>>> print(angles)
[  0  90 180 270]
>>> np.meshgrid(angles, radii)
[array([[  0,  90, 180, 270],
       [  0,  90, 180, 270],
       [  0,  90, 180, 270],
       [  0,  90, 180, 270],
       [  0,  90, 180, 270],
       [  0,  90, 180, 270]]), array([[ 0,  0,  0,  0],
       [10, 10, 10, 10],
       [20, 20, 20, 20],
       [30, 30, 30, 30],
       [40, 40, 40, 40],
       [50, 50, 50, 50]])]

 要記住的一點是繪圖函數需要以弧度而不是度數作為的角度(θ)的單位,因此如果您的數據是以度為單位(通常是),那么您需要使用NumPy radians函數將其轉換為弧度。

完成所有這些操作后,您可以正確地將數據導入輪廓繪圖功能,並且可以獲得一些極軸,以便繪制它。但是,如果你這樣做,你會發現你的軸看起來像這樣:

contour

您可以看到零度不在頂部,它位於“東”或“3點”位置,並且角度繞錯了方向!顯然,這些事情通常都是在數學中完成的——但在我的領域,特別是人們希望有一個頂部為零像指南針一樣的極坐標情景!

如果您嘗試找到如何執行此操作,您將找到一個StackOverflow答案,其中包含PolarAxes的精彩子類,可以解決這個問題。很贊的是,matplotlib允許你進行這種私人定制,但是如果你看下面接受的答案,你會找到一個名為set_theta_zero_location的函數的matplotlib文檔的鏈接。這個功能非常好地采用指南針方向(“N”或“E”或“NE”等)為零!類似地,函數set_theta_direction設置角度增加的方向。您需要做的就是從軸對象中調用它們:

ax.set_theta_zero_location( "N" )
ax.set_theta_direction( -1 )
上面的示例將為“正常”羅盤樣式繪圖設置圖,北部為零度,並且角度順時針增加。如果您發現這些代碼行出現錯誤,則需要更新matplotlib版本——這些方法僅在最新版本(v1.1.0)中添加。

所以,現在我們已經涵蓋了我逐漸學到的所有這些,我們可以把它們放在一個函數中。每當我想要繪制一個極坐標等高線圖時,我都會使用下面的函數,它對我來說很好。

我不能保證代碼對你有用,但希望這篇文章有用,你現在可以離開並在matplotlib中創建極坐標等高線圖。

 1 import numpy as np
 2 from matplotlib.pyplot import *
 3  
 4 def plot_polar_contour(values, azimuths, zeniths):
 5     """Plot a polar contour plot, with 0 degrees at the North.
 6  
 7     Arguments:
 8  
 9      * `values` -- A list (or other iterable - eg. a NumPy array) of the values to plot on the
10      contour plot (the `z` values)
11      * `azimuths` -- A list of azimuths (in degrees)
12      * `zeniths` -- A list of zeniths (that is, radii)
13  
14     The shapes of these lists are important, and are designed for a particular
15     use case (but should be more generally useful). The values list should be `len(azimuths) * len(zeniths)`
16     long with data for the first azimuth for all the zeniths, then the second azimuth for all the zeniths etc.
17  
18     This is designed to work nicely with data that is produced using a loop as follows:
19  
20     values = []
21     for azimuth in azimuths:
22       for zenith in zeniths:
23         # Do something and get a result
24         values.append(result)
25  
26     After that code the azimuths, zeniths and values lists will be ready to be passed into this function.
27  
28     """
29     theta = np.radians(azimuths)
30     zeniths = np.array(zeniths)
31  
32     values = np.array(values)
33     values = values.reshape(len(azimuths), len(zeniths))
34  
35     r, theta = np.meshgrid(zeniths, np.radians(azimuths))
36     fig, ax = subplots(subplot_kw=dict(projection='polar'))
37     ax.set_theta_zero_location("N")
38     ax.set_theta_direction(-1)
39     autumn()
40     cax = ax.contourf(theta, r, values, 30)
41     autumn()
42     cb = fig.colorbar(cax)
43     cb.set_label("Pixel reflectance")
44  
45     return fig, ax, cax

 https://www.pythonprogramming.in/plot-polar-graph-in-matplotlib.html

  

 


免責聲明!

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



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