将 x 轴分成 2 个以上的部分 (Python)
Break x axis in more than 2 parts (Python)
我正在尝试将 x 轴分成 5 个部分。关于如何将其分成两部分有很多答案,所以我遵循了相同的策略,但它不适用于超过 2 个部分。
有没有人成功地将一个轴分成两个以上的部分?
import numpy as np
from pylab import *
import matplotlib.pyplot as plt
fig,(ax,ax2,ax3,ax4,ax5) = plt.subplots(1,2,sharey=True)
ax.plot(wvln0,alb0,linestyle='-', marker='o', color='r',linewidth=1.0,label='Haze = 0T')
ax2.plot(wvln0,alb0,linestyle='-', marker='o', color='r',linewidth=1.0,label='Haze = 0T')
ax3.plot(wvln0,alb0,linestyle='-', marker='o', color='r',linewidth=1.0,label='Haze = 0T')
ax4.plot(wvln0,alb0,linestyle='-', marker='o', color='r',linewidth=1.0,label='Haze = 0T')
ax5.plot(wvln0,alb0,linestyle='-', marker='o', color='r',linewidth=1.0,label='Haze = 0T')
ax.set_xlim(0.15,1.10)
ax2.set_xlim(1.15,2.25)
ax3.set_xlim(1.20,1.30)
ax4.set_xlim(1.55,1.65)
ax5.set_xlim(1.95,2.15)
ax.spines['right'].set_visible(False)
ax2.spines['left'].set_visible(False)
ax.yaxis.tick_left()
ax.tick_params(labeltop='off') # don't put tick labels at the top
ax2.yaxis.tick_right()
plt.subplots_adjust(wspace=0.1)
axes = plt.gca()
axes.set_ylim([0.0,0.72])
plt.show()
Returns
Traceback (most recent call last):
File "/Users/jadecheclair/Documents/NASA Ames Research/NASA Codes/Wavlengths_Rages/wvln_alb.py", line 37, in <module>
fig,(ax,ax2,ax3,ax4,ax5) = plt.subplots(1,2,sharey=True)
ValueError: need more than 2 values to unpack
如果我尝试将行更改为
fig,(ax,ax2,ax3,ax4,ax5) = plt.subplots(1,2,3,4,5,sharey=True)
它returns
Traceback (most recent call last):
File "/Users/jadecheclair/Documents/NASA Ames Research/NASA Codes/Wavlengths_Rages/wvln_alb.py", line 37, in <module>
fig,(ax,ax2,ax3,ax4,ax5) = plt.subplots(1,2,3,4,5,sharey=True)
TypeError: subplots() got multiple values for keyword argument 'sharey'
问题 1
您没有正确调用 plt.subplots
。这里是默认用法
subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True, subplot_kw=None, gridspec_kw=None, **fig_kw)
好像你想要连续 5 个子图,所以设置 nrows=1
和 ncols=5
fig,axs = plt.subplots(nrows=1,ncols=5,sharey=True)
ax, ax2, ax3, ax4, ax5 = axs
问题 2
您需要正确设置书脊 - 您只希望最左边和最右边可见。用一个函数很容易做到这一点:
def multi_spine_adj( axs):
axs[0].spines['right'].set_visible(False)
axs[0].yaxis.tick_left()
for ax in axs[1:-1]:
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
axs[-1].spines['left'].set_visible(False)
axs[-1].yaxis.tick_right()
#wvln0 = np.linspace( 0,5,50) # make some fake data
#alb0 = np.random.random(50) #make some fake data
opts = {'linestyle':'-', 'marker':'o', 'color':'r','linewidth':1,'label':'Haze = 0T'}
fig,axs = plt.subplots(1,5,sharey=True)
xlims = [(0.15,1.10),
(1.15,2.25),
(1.20,1.30),
(1.55,1.65),
(1.95,2.15)]
for i,ax in enumerate(axs):
x1,x2 = xlims[i]
ax.plot(wvln0,alb0,**opts)
ax.set_xlim(x1,x2)
multi_spine_adj(axs)
plt.show()
提示
请注意如何轻松迭代 axs
,这会使您的代码更清晰且更易于修改(例如,如果您想添加更多中断)
这是一个示例,展示了我是如何通过在图中手动放置三个轴来实现的。
from __future__ import division, unicode_literals
import matplotlib.pyplot as plt
import numpy as np
plt.close('all')
# ----- PREPARE DATA ----
t = np.arange(0, 7 * 10**5, 10)
x = np.abs(np.sin(t/10.**2)) * 300
# ----- FIG CREATION ----
fig = plt.figure(figsize=(8, 5), facecolor='white')
# Margins (dimensions are in inches):
left_margin = 0.6 / fig.get_figwidth()
right_margin = 0.25 / fig.get_figwidth()
bottom_margin = 0.75 / fig.get_figheight()
top_margin = 0.25 / fig.get_figwidth()
mid_margin = 0.1 / fig.get_figwidth() # horizontal space between subplots
# ----- DEFINE PARAMETERS FOR EACH AXE ----
# Proportion of the figure's width taken by each axe (the sum must == 1):
f = [0.5, 0.3, 0.2]
xmin = [200, 50, 0] # xaxis minimum values for each axe
xmax = [8200, 200, 50] # xaxis maximum values for each axe
xscl = [2000, 50, 10] # xaxis scale for each axe
ymin, ymax = 0, 320 # yaxis minimum and maximum values
colors = ['green', 'blue', 'red'] # colors of each plot
labels = ['label1', 'label2', 'label3'] # labels of each plot for the legend
Naxes = len(f) # Total number of axes to add to the figure.
x0, y0 = left_margin, bottom_margin # origin point of the axe
h = 1 - (bottom_margin + top_margin) # height of the axe
# total width of the axes:
wtot = 1 - (left_margin + right_margin + (Naxes-1)*mid_margin)
lines = [] # to store handles for generating the legend later on
for i in range(Naxes):
# ----- AXES CREATION ----
w = wtot*f[i] # width of the current axe
ax = fig.add_axes([x0, y0, w, h], frameon=True, axisbg='none')
if i == 0: # First axe to the left
ax.spines['right'].set_visible(False)
ax.tick_params(right='off', labelright='off')
elif i == Naxes-1: # Last axe to the right
ax.spines['left'].set_visible(False)
ax.tick_params(left='off', labelleft='off',
right='off', labelright='off')
else:
ax.spines['left'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.tick_params(left='off', labelleft='off',
right='off', labelright='off')
# origin point of the next axe to be added to the figure:
x0 += w + mid_margin
# ----- SETUP XTICKS ----
if i == Naxes-1:
xticks = np.arange(xmin[i], xmax[i] + xscl[i]/2, xscl[i])
else:
xticks = np.arange(xmin[i]+xscl[i], xmax[i] + xscl[i]/2, xscl[i])
ax.set_xticks(xticks)
ax.xaxis.set_ticks_position('bottom')
ax.tick_params(axis='x', direction='out', labelsize=8)
xticks_minor = np.arange(xmin[i], xmax[i] + xscl[i]/5., xscl[i] / 5.)
ax.set_xticks(xticks_minor, minor=True)
ax.tick_params(axis='x', which='minor', direction='out')
# ----- PLOT DATA ----
line, = ax.plot(t, x, color=colors[i])
lines.append(line) # for plotting the legend
ax.axis([xmin[i], xmax[i], ymin, ymax])
ax.invert_xaxis()
# ---- SET XAXIS LABEL ----
fig.axes[0].set_xlabel('Time (years)', fontsize=12, va='bottom', ha='center')
fig.axes[0].xaxis.set_label_coords(0.5, 0.05, transform=fig.transFigure)
# ----- LEGEND ----
fig.axes[0].legend(lines, labels, loc=(0.1, 0.1), ncol=1, fancybox=True,
fontsize=12)
# ----- SHOW FIG ----
fig.savefig('SingleAxeThreeScale.png')
plt.show()
这导致:
我正在尝试将 x 轴分成 5 个部分。关于如何将其分成两部分有很多答案,所以我遵循了相同的策略,但它不适用于超过 2 个部分。 有没有人成功地将一个轴分成两个以上的部分?
import numpy as np
from pylab import *
import matplotlib.pyplot as plt
fig,(ax,ax2,ax3,ax4,ax5) = plt.subplots(1,2,sharey=True)
ax.plot(wvln0,alb0,linestyle='-', marker='o', color='r',linewidth=1.0,label='Haze = 0T')
ax2.plot(wvln0,alb0,linestyle='-', marker='o', color='r',linewidth=1.0,label='Haze = 0T')
ax3.plot(wvln0,alb0,linestyle='-', marker='o', color='r',linewidth=1.0,label='Haze = 0T')
ax4.plot(wvln0,alb0,linestyle='-', marker='o', color='r',linewidth=1.0,label='Haze = 0T')
ax5.plot(wvln0,alb0,linestyle='-', marker='o', color='r',linewidth=1.0,label='Haze = 0T')
ax.set_xlim(0.15,1.10)
ax2.set_xlim(1.15,2.25)
ax3.set_xlim(1.20,1.30)
ax4.set_xlim(1.55,1.65)
ax5.set_xlim(1.95,2.15)
ax.spines['right'].set_visible(False)
ax2.spines['left'].set_visible(False)
ax.yaxis.tick_left()
ax.tick_params(labeltop='off') # don't put tick labels at the top
ax2.yaxis.tick_right()
plt.subplots_adjust(wspace=0.1)
axes = plt.gca()
axes.set_ylim([0.0,0.72])
plt.show()
Returns
Traceback (most recent call last):
File "/Users/jadecheclair/Documents/NASA Ames Research/NASA Codes/Wavlengths_Rages/wvln_alb.py", line 37, in <module>
fig,(ax,ax2,ax3,ax4,ax5) = plt.subplots(1,2,sharey=True)
ValueError: need more than 2 values to unpack
如果我尝试将行更改为
fig,(ax,ax2,ax3,ax4,ax5) = plt.subplots(1,2,3,4,5,sharey=True)
它returns
Traceback (most recent call last):
File "/Users/jadecheclair/Documents/NASA Ames Research/NASA Codes/Wavlengths_Rages/wvln_alb.py", line 37, in <module>
fig,(ax,ax2,ax3,ax4,ax5) = plt.subplots(1,2,3,4,5,sharey=True)
TypeError: subplots() got multiple values for keyword argument 'sharey'
问题 1
您没有正确调用 plt.subplots
。这里是默认用法
subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True, subplot_kw=None, gridspec_kw=None, **fig_kw)
好像你想要连续 5 个子图,所以设置 nrows=1
和 ncols=5
fig,axs = plt.subplots(nrows=1,ncols=5,sharey=True)
ax, ax2, ax3, ax4, ax5 = axs
问题 2
您需要正确设置书脊 - 您只希望最左边和最右边可见。用一个函数很容易做到这一点:
def multi_spine_adj( axs):
axs[0].spines['right'].set_visible(False)
axs[0].yaxis.tick_left()
for ax in axs[1:-1]:
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
axs[-1].spines['left'].set_visible(False)
axs[-1].yaxis.tick_right()
#wvln0 = np.linspace( 0,5,50) # make some fake data
#alb0 = np.random.random(50) #make some fake data
opts = {'linestyle':'-', 'marker':'o', 'color':'r','linewidth':1,'label':'Haze = 0T'}
fig,axs = plt.subplots(1,5,sharey=True)
xlims = [(0.15,1.10),
(1.15,2.25),
(1.20,1.30),
(1.55,1.65),
(1.95,2.15)]
for i,ax in enumerate(axs):
x1,x2 = xlims[i]
ax.plot(wvln0,alb0,**opts)
ax.set_xlim(x1,x2)
multi_spine_adj(axs)
plt.show()
提示
请注意如何轻松迭代 axs
,这会使您的代码更清晰且更易于修改(例如,如果您想添加更多中断)
这是一个示例,展示了我是如何通过在图中手动放置三个轴来实现的。
from __future__ import division, unicode_literals
import matplotlib.pyplot as plt
import numpy as np
plt.close('all')
# ----- PREPARE DATA ----
t = np.arange(0, 7 * 10**5, 10)
x = np.abs(np.sin(t/10.**2)) * 300
# ----- FIG CREATION ----
fig = plt.figure(figsize=(8, 5), facecolor='white')
# Margins (dimensions are in inches):
left_margin = 0.6 / fig.get_figwidth()
right_margin = 0.25 / fig.get_figwidth()
bottom_margin = 0.75 / fig.get_figheight()
top_margin = 0.25 / fig.get_figwidth()
mid_margin = 0.1 / fig.get_figwidth() # horizontal space between subplots
# ----- DEFINE PARAMETERS FOR EACH AXE ----
# Proportion of the figure's width taken by each axe (the sum must == 1):
f = [0.5, 0.3, 0.2]
xmin = [200, 50, 0] # xaxis minimum values for each axe
xmax = [8200, 200, 50] # xaxis maximum values for each axe
xscl = [2000, 50, 10] # xaxis scale for each axe
ymin, ymax = 0, 320 # yaxis minimum and maximum values
colors = ['green', 'blue', 'red'] # colors of each plot
labels = ['label1', 'label2', 'label3'] # labels of each plot for the legend
Naxes = len(f) # Total number of axes to add to the figure.
x0, y0 = left_margin, bottom_margin # origin point of the axe
h = 1 - (bottom_margin + top_margin) # height of the axe
# total width of the axes:
wtot = 1 - (left_margin + right_margin + (Naxes-1)*mid_margin)
lines = [] # to store handles for generating the legend later on
for i in range(Naxes):
# ----- AXES CREATION ----
w = wtot*f[i] # width of the current axe
ax = fig.add_axes([x0, y0, w, h], frameon=True, axisbg='none')
if i == 0: # First axe to the left
ax.spines['right'].set_visible(False)
ax.tick_params(right='off', labelright='off')
elif i == Naxes-1: # Last axe to the right
ax.spines['left'].set_visible(False)
ax.tick_params(left='off', labelleft='off',
right='off', labelright='off')
else:
ax.spines['left'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.tick_params(left='off', labelleft='off',
right='off', labelright='off')
# origin point of the next axe to be added to the figure:
x0 += w + mid_margin
# ----- SETUP XTICKS ----
if i == Naxes-1:
xticks = np.arange(xmin[i], xmax[i] + xscl[i]/2, xscl[i])
else:
xticks = np.arange(xmin[i]+xscl[i], xmax[i] + xscl[i]/2, xscl[i])
ax.set_xticks(xticks)
ax.xaxis.set_ticks_position('bottom')
ax.tick_params(axis='x', direction='out', labelsize=8)
xticks_minor = np.arange(xmin[i], xmax[i] + xscl[i]/5., xscl[i] / 5.)
ax.set_xticks(xticks_minor, minor=True)
ax.tick_params(axis='x', which='minor', direction='out')
# ----- PLOT DATA ----
line, = ax.plot(t, x, color=colors[i])
lines.append(line) # for plotting the legend
ax.axis([xmin[i], xmax[i], ymin, ymax])
ax.invert_xaxis()
# ---- SET XAXIS LABEL ----
fig.axes[0].set_xlabel('Time (years)', fontsize=12, va='bottom', ha='center')
fig.axes[0].xaxis.set_label_coords(0.5, 0.05, transform=fig.transFigure)
# ----- LEGEND ----
fig.axes[0].legend(lines, labels, loc=(0.1, 0.1), ncol=1, fancybox=True,
fontsize=12)
# ----- SHOW FIG ----
fig.savefig('SingleAxeThreeScale.png')
plt.show()
这导致: