我正在处理一个由网格中的大量极坐标图组成的图,所有这些图都在径向轴上共享一个共同的比例。为了适应图形,每个图需要非常小,但是当我缩小轴的尺寸时,径向轴的刻度标签看起来很拥挤且难以辨认,并且模糊了我试图绘制的数据。
例如:
import numpy as np
from matplotlib import pyplot as plt
fig, axes = plt.subplots(1, 4, figsize=(9, 2), subplot_kw=dict(polar=True))
theta = np.r_[np.linspace(0, 2*np.pi, 12), 0]
for aa in axes.flat:
x = np.random.rand(12)
aa.plot(theta, np.r_[x, x[0]], '-sb')
aa.set_rlim(0, 1)
fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9, wspace=0.5)
我意识到通过减小字体大小和径向刻度的数量可以部分地减轻问题,但我更愿意避免刻度标签与我的数据完全重叠。相反,我希望有一个漂浮的'位于图之外的径向轴,如下所示:
使用正常的笛卡尔图我会使用ax.spine['left'].set_position(...)
,但PolarAxesSubplot
只有一个u'polar'
脊椎无法抵消。有一个很好的'为极坐标图创建浮动径向轴的方法,理想情况是更新其比例和限制以匹配极坐标图径向轴的任何变化?
答案 0 :(得分:3)
这不完全是你想要的,但它可能会给你一个关于如何准确定位极轴的标签的提示:
import numpy as np
from matplotlib import pyplot as plt
fig, axes = plt.subplots(1, 4, figsize=(9, 2), subplot_kw=dict(polar=True))
theta = np.r_[np.linspace(0, 2*np.pi, 12), 0]
for aa in axes.flat:
x = np.random.rand(12)
aa.plot(theta, np.r_[x, x[0]], '-sb')
aa.set_rlim(0, 1)
plt.draw()
ax = axes[-1]
for r, t in zip(ax.yaxis.get_ticklocs(), ax.yaxis.get_ticklabels()):
ax.text(np.pi/2, r, '$\cdot$'*20 + t.get_text(), ha='left', va='center',
fontsize=10, color='0.25')
for ax in axes:
ax.yaxis.set_ticklabels([])
fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9, wspace=0.5)
fig.savefig('test.png', bbox_inches='tight')
答案 1 :(得分:2)
也许我们可以在上面叠加另一个情节:
fig, axes = plt.subplots(1, 4, figsize=(9, 2), subplot_kw=dict(polar=True))
for aa in axes.flat:
aa.plot(theta, r, '-sb')
aa.set_rlim(0, 1)
aa.set_yticklabels([])
box=axes[0].get_position()
axl=fig.add_axes([box.xmin/2, #put it half way between the edge of the 1st subplot and the left edge of the figure
0.5*(box.ymin+box.ymax), #put the origin at the same height of the origin of the polar plots
box.width/40, #Doesn't really matter, we will set everything invisible, except the y axis
box.height*0.4], #fig.subplots_adjust will not adjust this axis, so we will need to manually set the height to 0.4 (half of 0.9-0.1)
axisbg=None) #transparent background.
axl.spines['top'].set_visible(False)
axl.spines['right'].set_visible(False)
axl.spines['bottom'].set_visible(False)
axl.yaxis.set_ticks_position('both')
axl.xaxis.set_ticks_position('none')
axl.set_xticklabels([])
axl.set_ylim(0,1)
axl.set_ylabel('$R$\t', rotation=0)
fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9, wspace=0.5)
事实证明subplots_adjust
也会影响叠加轴。如果我们检查fig
内的轴列表,叠加轴就在那里(如果有疑问,请检查 site-packages \ matplotlib \ figure.py ):
In [27]:
fig.axes
Out[27]:
[<matplotlib.axes.PolarAxesSubplot at 0x9714650>,
<matplotlib.axes.PolarAxesSubplot at 0x9152730>,
<matplotlib.axes.PolarAxesSubplot at 0x9195b90>,
<matplotlib.axes.PolarAxesSubplot at 0x91878b0>,
<matplotlib.axes.Axes at 0x9705a90>]
真正的问题是wspace=0.5
不仅会影响极坐标图的宽度,还会影响高度(因此方面保持不变)。但对于非极性叠加轴,它只影响宽度。因此,需要额外的宽度修改,解决方案是:
fig, axes = plt.subplots(1, 4, figsize=(10, 2), subplot_kw=dict(polar=True))
for aa in axes.flat:
aa.plot(theta, r, '-sb')
aa.set_rlim(0, 1)
aa.set_yticklabels([])
#fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9, wspace=0.5)
box=axes[0].get_position()
axl=fig.add_axes([box.xmin/2,
0.5*(box.ymin+box.ymax),
box.width/40,
box.height*0.5],
axisbg=None)
#fig.add_axes([box.xmin, box.ymin, box.width, box.height])
axl.spines['top'].set_visible(False)
axl.spines['right'].set_visible(False)
axl.spines['bottom'].set_visible(False)
axl.yaxis.set_ticks_position('both')
axl.xaxis.set_ticks_position('none')
axl.set_xticklabels([])
axl.set_ylim(0,1)
axl.set_ylabel('$R$\t', rotation=0)
w_pre_scl=box.width
fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9, wspace=0.5)
ratio=axes[0].get_position().width/w_pre_scl
axlb=axl.get_position()
axl.set_position([axlb.xmin, axlb.ymin, axlb.width, axlb.height*ratio])
如果没有wspace=0.5
,则最后几行没有净影响:
fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9)
#ratio=axes[0].get_position().width/w_pre_scl
#axlb=axl.get_position()
#axl.set_position([axlb.xmin, axlb.ymin, axlb.width, axlb.height*ratio])
答案 2 :(得分:2)
根据Saullo的回答,这里有一个看起来稍微好看的黑客,包括在数据坐标中绘制刻度,然后在x中应用固定的翻译:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import transforms
theta = np.linspace(0, 2 * np.pi, 13, endpoint=True)
fig, axes = plt.subplots(1, 4, figsize=(5, 2), subplot_kw=dict(polar=True))
for aa in axes.flat:
aa.hold(True)
r = np.random.rand(12)
r = np.r_[r, r[0]]
aa.plot(theta, r, '-sb')
aa.set_rlim(0, 1)
aa.set_yticklabels([])
factor = 1.1
d = axes[0].get_yticks()[-1] * factor
r_tick_labels = [0] + axes[0].get_yticks()
r_ticks = (np.array(r_tick_labels) ** 2 + d ** 2) ** 0.5
theta_ticks = np.arcsin(d / r_ticks) + np.pi / 2
r_axlabel = (np.mean(r_tick_labels) ** 2 + d ** 2) ** 0.5
theta_axlabel = np.arcsin(d / r_axlabel) + np.pi / 2
# fixed offsets in x
offset_spine = transforms.ScaledTranslation(-100, 0, axes[0].transScale)
offset_ticklabels = transforms.ScaledTranslation(-10, 0, axes[0].transScale)
offset_axlabel = transforms.ScaledTranslation(-40, 0, axes[0].transScale)
# apply these to the data coordinates of the line/ticks
trans_spine = axes[0].transData + offset_spine
trans_ticklabels = trans_spine + offset_ticklabels
trans_axlabel = trans_spine + offset_axlabel
# plot the 'spine'
axes[0].plot(theta_ticks, r_ticks, '-_k', transform=trans_spine,
clip_on=False)
# plot the 'tick labels'
for ii in xrange(len(r_ticks)):
axes[0].text(theta_ticks[ii], r_ticks[ii], "%.1f" % r_tick_labels[ii],
ha="right", va="center", clip_on=False,
transform=trans_ticklabels)
# plot the 'axis label'
axes[0].text(theta_axlabel, r_axlabel, '$r$', fontsize='xx-large',
ha='right', va='center', clip_on=False, transform=trans_axlabel)
fig.savefig('test.png', bbox_inches='tight')
同样,这具有以下优点:当图形尺寸改变时,刻度线的y位置将相对于极坐标图的径向轴保持正确。但是(在从@SaulloCastro更新之前),由于x-offset是以点为单位指定的,并且是固定的,当图形大小改变时浮动轴将无法正确定位,并且最终可能与极坐标图重叠: