fid*_*tas 6 python matplotlib multiple-axes
我尝试在一个图中绘制两个极坐标图.见下面的代码:
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
Run Code Online (Sandbox Code Playgroud)

条形的长度是数据库(该扇区的采样点数).条形图的颜色显示相应扇区中某些值区(例如2.5-5 m/s)的频率(蓝色:低,红色:高).蓝蜘蛛图显示每个扇区的平均值.
在所示的图中,每个图的值是相似的,但这种情况很少见.我需要将第二个绘图分配给另一个轴并在另一个方向上显示该轴.
编辑:
在乔的好答案之后,我得到了这个数字的结果.
这几乎是我想要实现的一切.但有些观点我无法弄清楚.
该图用于动态变化的数据库.因此,我需要一种动态的方式来获得圆圈的相同位置.直到现在我解决它:
start, end = ax2.get_ylim()
ax2.yaxis.set_ticks(np.arange(0, end, end / len(ax.yaxis.get_ticklocs())))
Run Code Online (Sandbox Code Playgroud)
意思是:对于第二轴,我改变刻度,以便将刻度线适合第一轴的一个.在大多数情况下,我得到一些小数位,但我不希望这样,因为它破坏了情节的清晰度.有没有办法更聪明地解决这个问题?
ytics(径向的)从0到倒数第二个圆.我怎样才能实现从第一个圆到最后一个圆(边界)的值?对于第一轴也是如此.
因此,据我所知,您希望在同一极坐标图上显示具有不同幅度的数据.基本上你问的是如何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()
Run Code Online (Sandbox Code Playgroud)

但是,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()
Run Code Online (Sandbox Code Playgroud)

这就是我们想要的,但起初它看起来相当糟糕.一个改进是刻度标签与我们正在绘制的内容相对应:
plt.setp(ax2.get_yticklabels(), color='darkgreen')
plt.setp(ax.get_yticklabels(), color='darkblue')
Run Code Online (Sandbox Code Playgroud)

但是,我们仍然有双网格,这是相当混乱的.解决这个问题的一个简单方法是手动设置r限制(和/或r-ticks),使得网格将相互叠加.或者,您可以编写自定义定位器来自动执行此操作.让我们坚持这里简单的方法:
ax.set_rlim([0, 5])
ax2.set_rlim([0, 1])
Run Code Online (Sandbox Code Playgroud)

警告:因为共享轴不适用于极坐标图,所以我上面的实施将会出现任何改变原始轴位置的问题.例如,向图中添加颜色条将导致各种问题.可以解决这个问题,但我已经离开了那个部分.如果您需要,请告诉我,我将添加一个示例.
无论如何,这是生成最终数字的完整独立代码:
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()
Run Code Online (Sandbox Code Playgroud)