2010-03-10 140 views
26

我正在使用matplotlib和numpy來製作極座標圖。以下是一些示例代碼:如何使matplotlib極座標圖中的角度在頂部0°順時針旋轉?

import numpy as N 
import matplotlib.pyplot as P 

angle = N.arange(0, 360, 10, dtype=float) * N.pi/180.0 
arbitrary_data = N.abs(N.sin(angle)) + 0.1 * (N.random.random_sample(size=angle.shape) - 0.5) 

P.clf() 
P.polar(angle, arbitrary_data) 
P.show() 

您會注意到0°位於繪圖的3點位置,並且角度逆時針旋轉。對於我的數據可視化目的而言,在12點鐘處具有0°並且角度順時針旋轉會更有用。除了旋轉數據並手動更改軸標籤之外,是否還有任何方法可以執行此操作

回答

18

我發現了它--matplotlib允許您創建自定義投影。我創建了一個從PolarAxes繼承。

import numpy as N 
import matplotlib.pyplot as P 

from matplotlib.projections import PolarAxes, register_projection 
from matplotlib.transforms import Affine2D, Bbox, IdentityTransform 

class NorthPolarAxes(PolarAxes): 
    ''' 
    A variant of PolarAxes where theta starts pointing north and goes 
    clockwise. 
    ''' 
    name = 'northpolar' 

    class NorthPolarTransform(PolarAxes.PolarTransform): 
     def transform(self, tr): 
      xy = N.zeros(tr.shape, N.float_) 
      t = tr[:, 0:1] 
      r = tr[:, 1:2] 
      x = xy[:, 0:1] 
      y = xy[:, 1:2] 
      x[:] = r * N.sin(t) 
      y[:] = r * N.cos(t) 
      return xy 

     transform_non_affine = transform 

     def inverted(self): 
      return NorthPolarAxes.InvertedNorthPolarTransform() 

    class InvertedNorthPolarTransform(PolarAxes.InvertedPolarTransform): 
     def transform(self, xy): 
      x = xy[:, 0:1] 
      y = xy[:, 1:] 
      r = N.sqrt(x*x + y*y) 
      theta = N.arctan2(y, x) 
      return N.concatenate((theta, r), 1) 

     def inverted(self): 
      return NorthPolarAxes.NorthPolarTransform() 

    def _set_lim_and_transforms(self): 
     PolarAxes._set_lim_and_transforms(self) 
     self.transProjection = self.NorthPolarTransform() 
     self.transData = (
      self.transScale + 
      self.transProjection + 
      (self.transProjectionAffine + self.transAxes)) 
     self._xaxis_transform = (
      self.transProjection + 
      self.PolarAffine(IdentityTransform(), Bbox.unit()) + 
      self.transAxes) 
     self._xaxis_text1_transform = (
      self._theta_label1_position + 
      self._xaxis_transform) 
     self._yaxis_transform = (
      Affine2D().scale(N.pi * 2.0, 1.0) + 
      self.transData) 
     self._yaxis_text1_transform = (
      self._r_label1_position + 
      Affine2D().scale(1.0/360.0, 1.0) + 
      self._yaxis_transform) 

register_projection(NorthPolarAxes) 

angle = N.arange(0, 360, 10, dtype=float) * N.pi/180.0 
arbitrary_data = (N.abs(N.sin(angle)) + 0.1 * 
    (N.random.random_sample(size=angle.shape) - 0.5)) 

P.clf() 
P.subplot(1, 1, 1, projection='northpolar') 
P.plot(angle, arbitrary_data) 
P.show() 
+1

太棒了,這應該包含在他們的自定義投影示例中。 – Mark 2010-03-12 19:04:30

+1

我建議將它合併到代碼庫中。 – 2011-09-18 17:23:34

+0

任何想法如何使用FigureCanvasGTKAgg得到這個工作? – Sardathrion 2012-07-02 12:41:56

4

你可以修改你的matplotlib/projections/polar.py。

凡說:

def transform(self, tr): 
     xy = npy.zeros(tr.shape, npy.float_) 
     t = tr[:, 0:1] 
     r = tr[:, 1:2] 
     x = xy[:, 0:1] 
     y = xy[:, 1:2] 
     x[:] = r * npy.cos(t) 
     y[:] = r * npy.sin(t) 
     return xy 

讓它說:

def transform(self, tr): 
     xy = npy.zeros(tr.shape, npy.float_) 
     t = tr[:, 0:1] 
     r = tr[:, 1:2] 
     x = xy[:, 0:1] 
     y = xy[:, 1:2] 
     x[:] = - r * npy.sin(t) 
     y[:] = r * npy.cos(t) 
     return xy 

我並沒有真正嘗試它,你可能需要調整X [:]和Y [:]分配到你的口味。此更改將影響所有使用matplotlib極座標圖的程序。

+0

這是巧妙的,但修補代碼是一種作弊的,不是嗎?不過,你給了我一個想法。 Matplotlib允許你創建任何形式的轉換;也許我可以用我正在尋找的變換編寫一個交替的polar()函數。 – ptomato 2010-03-11 10:07:38

2

兩個倒置程序應該使用完整路徑轉換:

return NorthPolarAxes.InvertedNorthPolarTransform() 

return NorthPolarAxes.NorthPolarTransform() 

現在,如NorthPolarAxesSubplot NorthPolarAxes的自動創建的子類可以訪問轉換功能。

希望這會有所幫助。

28

更新此問題,在Matplotlib 1.1中,現在有兩個方法在PolarAxes中設置theta方向(CW/CCW)和theta = 0的位置。

退房 http://matplotlib.sourceforge.net/devel/add_new_projection.html#matplotlib.projections.polar.PolarAxes

具體來說,見set_theta_direction()set_theta_offset()

很多人試圖做類似指南針的情節似乎。

+1

如果你有一個極軸* ax *:** ax.set_theta_offset(0.5 * numpy.pi)** – zinjaai 2015-02-12 08:48:15

14

擴大klimaat的回答有一個例子:

import math 
angle=[0.,5.,10.,15.,20.,25.,30.,35.,40.,45.,50.,55.,60.,65.,70.,75.,\ 
     80.,85.,90.,95.,100.,105.,110.,115.,120.,125.] 

angle = [math.radians(a) for a in angle] 


lux=[12.67,12.97,12.49,14.58,12.46,12.59,11.26,10.71,17.74,25.95,\ 
    15.07,7.43,6.30,6.39,7.70,9.19,11.30,13.30,14.07,15.92,14.70,\ 
    10.70,6.27,2.69,1.29,0.81] 

import matplotlib.pyplot as P 
import matplotlib 
P.clf() 
sp = P.subplot(1, 1, 1, projection='polar') 
sp.set_theta_zero_location('N') 
sp.set_theta_direction(-1) 
P.plot(angle, lux) 
P.show()