2013-10-25 52 views
5

我尝试在一个图中绘制两个极坐标图。请参见下面的代码:将第二个轴添加到极坐标图

fig = super(PlotWindPowerDensity, self).get_figure() 
    rect = [0.1, 0.1, 0.8, 0.8] 
    ax = WindSpeedDirectionAxes(fig, rect) 

    self.values_dict = collections.OrderedDict(sorted(self.values_dict.items())) 
    values = self.values_dict.items() 
    di, wpd = zip(*values) 
    wpd = np.array(wpd).astype(np.double) 
    wpdmask = np.isfinite(wpd) 
    theta = self.radar_factory(int(len(wpd))) 

    # spider plot 
    ax.plot(theta[wpdmask], wpd[wpdmask], color = 'b', alpha = 0.5) 
    ax.fill(theta[wpdmask], wpd[wpdmask], facecolor = 'b', alpha = 0.5) 

    # bar plot 
    ax.plot_bar(table=self.table, sectors=self.sectors, speedbins=self.wpdbins, option='wind_power_density', colorfn=get_sequential_colors) 

    fig.add_axes(ax) 
    return fig 

Result till now

的条的长度是数据的基础上(对于该扇区多少采样点)。条纹的颜色显示相应扇区(蓝色:低,红色:高)中某些值框(例如2.5-5 m/s)的频率。蓝蜘蛛图显示每个扇区的平均值。

在所示的图中,每个图的值是相似的,但这很少见。我需要将第二个绘图分配给另一个轴并在另一个方向上显示此轴。

编辑:

乔不错的答案后,我得到的数字的结果。 provisional result 这几乎是我想要实现的一切。但有一些我无法解决的问题。

  1. 该图用于动态变化的数据库。因此,我需要一种动态的方式来获得相同的圈子位置。到现在我解决它:

    start, end = ax2.get_ylim() 
    ax2.yaxis.set_ticks(np.arange(0, end, end/len(ax.yaxis.get_ticklocs()))) 
    

    指:对于第二轴线I改变蜱为了适应ticklocs到第一轴的一个的。 在大多数情况下,我会得到一些小数位,但我不想那样,因为它破坏了情节的清晰度。有没有办法更巧妙地解决这个问题?

  2. ytics(径向的)范围从0到倒数第二个圆。我怎样才能实现从第一个圈到最后一个圈(边界)的值?与第一轴相同。

+0

请修复您的缩进。看起来您正在使用大量自定义的类,这样可以排除困难。你可以用标准的matplotlib对象来演示你想要的吗? – tacaswell

+0

感谢您提供图像。我的信誉分数太低了,无法为我自己做。 – fidelitas

+1

关于如何获得最后一个半径标签显示的第二个问题,只是因为您使用'np.arange'设置了刻度。 'arange'在端点之前停止(例如'np.arange(0,0.5,0.1)'产生'array([0.0,0.1,0.2,0.3,0.4])'')。如果您想包含端点,请使用'end + dx'(其中'dx'是您的间隔)。 –

回答

6

所以,据我所知,你想在同一个极坐标图上显示不同大小的数据。基本上你问的是如何为极坐标轴做类似twinx的操作。

举个例子来说明这个问题,这将是很好,以显示在不同的规模比蓝色系列下面的情节绿色系列,同时保持它们对便于比较:

相同极轴
import numpy as np 
import matplotlib.pyplot as plt 

numpoints = 30 
theta = np.linspace(0, 2*np.pi, numpoints) 
r1 = np.random.random(numpoints) 
r2 = 5 * np.random.random(numpoints) 

params = dict(projection='polar', theta_direction=-1, theta_offset=np.pi/2) 
fig, ax = plt.subplots(subplot_kw=params) 

ax.fill_between(theta, r2, color='blue', alpha=0.5) 
ax.fill_between(theta, r1, color='green', alpha=0.5) 

plt.show() 

enter image description here

然而,ax.twinx()不适用于极坐标图工作。

可以解决这个问题,但这不是非常简单。这里有一个例子:

import numpy as np 
import matplotlib.pyplot as plt 

def main(): 
    numpoints = 30 
    theta = np.linspace(0, 2*np.pi, numpoints) 
    r1 = np.random.random(numpoints) 
    r2 = 5 * np.random.random(numpoints) 

    params = dict(projection='polar', theta_direction=-1, theta_offset=np.pi/2) 
    fig, ax = plt.subplots(subplot_kw=params) 
    ax2 = polar_twin(ax) 

    ax.fill_between(theta, r2, color='blue', alpha=0.5) 
    ax2.fill_between(theta, r1, color='green', alpha=0.5) 
    plt.show() 

def polar_twin(ax): 
    ax2 = ax.figure.add_axes(ax.get_position(), projection='polar', 
          label='twin', frameon=False, 
          theta_direction=ax.get_theta_direction(), 
          theta_offset=ax.get_theta_offset()) 
    ax2.xaxis.set_visible(False) 
    # There should be a method for this, but there isn't... Pull request? 
    ax2._r_label_position._t = (22.5 + 180, 0.0) 
    ax2._r_label_position.invalidate() 
    # Ensure that original axes tick labels are on top of plots in twinned axes 
    for label in ax.get_yticklabels(): 
     ax.figure.texts.append(label) 
    return ax2 

main() 

enter image description here

就是我们想要的东西,但它看起来相当不错,在第一。一个改进是将刻度标记对应于我们正在密谋什么:

plt.setp(ax2.get_yticklabels(), color='darkgreen') 
plt.setp(ax.get_yticklabels(), color='darkblue') 

enter image description here

但是,我们仍然有双网格,这是相当混乱。一个简单的方法是手动设置r-限制(和/或r-ticks),使得网格彼此重叠。或者,您可以编写自定义定位器来自动执行此操作。让我们坚持使用简单的方法在这里:

ax.set_rlim([0, 5]) 
ax2.set_rlim([0, 1]) 

enter image description here

警告:因为共享轴不为极坐标图工作,implmentation我上面将有任何改变的位置问题原始的轴。例如,向图中添加一个颜色条会导致各种问题。有可能解决这个问题,但我已经放弃了这部分。如果你需要它,让我知道,我会添加一个例子。

无论如何,这里是完整的,独立的代码来生成最终的数字:

import numpy as np 
import matplotlib.pyplot as plt 
np.random.seed(1977) 

def main(): 
    numpoints = 30 
    theta = np.linspace(0, 2*np.pi, numpoints) 
    r1 = np.random.random(numpoints) 
    r2 = 5 * np.random.random(numpoints) 

    params = dict(projection='polar', theta_direction=-1, theta_offset=np.pi/2) 
    fig, ax = plt.subplots(subplot_kw=params) 
    ax2 = polar_twin(ax) 

    ax.fill_between(theta, r2, color='blue', alpha=0.5) 
    ax2.fill_between(theta, r1, color='green', alpha=0.5) 

    plt.setp(ax2.get_yticklabels(), color='darkgreen') 
    plt.setp(ax.get_yticklabels(), color='darkblue') 
    ax.set_ylim([0, 5]) 
    ax2.set_ylim([0, 1]) 

    plt.show() 

def polar_twin(ax): 
    ax2 = ax.figure.add_axes(ax.get_position(), projection='polar', 
          label='twin', frameon=False, 
          theta_direction=ax.get_theta_direction(), 
          theta_offset=ax.get_theta_offset()) 
    ax2.xaxis.set_visible(False) 

    # There should be a method for this, but there isn't... Pull request? 
    ax2._r_label_position._t = (22.5 + 180, 0.0) 
    ax2._r_label_position.invalidate() 

    # Bit of a hack to ensure that the original axes tick labels are on top of 
    # whatever is plotted in the twinned axes. Tick labels will be drawn twice. 
    for label in ax.get_yticklabels(): 
     ax.figure.texts.append(label) 

    return ax2 

if __name__ == '__main__': 
    main() 
+0

这个答案非常好,我想给它多个upvote,但我不能:(我会尽量让自己的答案和这个一样好。 –

+0

@GamesBrainiac - 谢谢! –

+0

谢谢你**非常很多**为你的详细和很容易理解的答案,它为我工作得很好。还有一些问题,在我的第一篇文章中提到。 – fidelitas

1

只需添加到@JoeKington的(大)的答案,我发现,“黑客以保证原始轴刻度标签在绘制在孪生轴上的任何东西之上“并不适用于我,所以作为我已经使用的替代方案:

from matplotlib.ticker import MaxNLocator 

#Match the tick point locations by setting the same number of ticks in the 
# 2nd axis as the first  
ax2.yaxis.set_major_locator(MaxNLocator(nbins=len(ax1.get_yticks()))) 

#Set the last tick as the plot limit 
ax2.set_ylim(0, ax2.get_yticks()[-1]) 

#Remove the tick label at zero 
ax2.yaxis.get_major_ticks()[0].label1.set_visible(False)