Plotly:如何在同一个子图中显示超过 2 x-axes titles/ranges?
Plotly: How to show more than 2 x-axes titles/ranges on the same subplot?
我正在使用 Plotly 并使用共享的 y-axis 和不同的 x-axes 制作散点图子图。我试图使用图形 object (fig['layout'][数据索引]) 语法来显示多个堆叠的 x-axes 及其各自的范围。通过将 'top' 和 'bottom' 分配给图形布局的 side 属性,我只成功地在每个子图中显示了两个 xaxes 和范围。下图中右起第二列应该显示系列 T5、T6 和 T7 的 titles/ranges,但只显示 T5 和 T7 的标题和范围。
是否可以在 Plotly 中的同一个子图中显示超过 2 个 x-axes title/ranges? For an implemented example, Matplotlib supports showing multiple stacked axes
感谢 Vestland,关键是使用图形布局的位置属性并缩放 y-axis 以正确适应调整。基于 Vestland 示例代码的多轴的完整实现,请参见下面的 [monstrosity]。
您需要 make_subplots(rows=1, cols=2)
、add_traces()
和 fig.update_layout(xaxis=dict(domain=...)
的精确组合:
使用 fig=make_subplots(rows=1, cols=2)
设置一个“常规”子图,并按照 here.
所述包含两条轨迹
使用 fig.add_trace(go.Scatter([...[, xaxis="x3"))
添加具有自己的 x 轴的第三条轨迹
然后,调整子图 1 为 xaxis3
腾出空间,使用:fig.update_layout(xaxis3=dict(anchor="free", overlaying="x1", position=0.0))
使用 fig.update_layout([...], yaxis2=dict(domain=[0.1, 1]))
进行一些最终调整
之所以要考虑domain
,是因为point 3
中的position
属性不能为负,必须腾出空间对于双 x-axes 不知何故。结果如下:
情节
完整代码:
from plotly.subplots import make_subplots
import plotly.graph_objects as go
# initial subplot with two traces
fig = make_subplots(rows=1, cols=2)
fig.add_trace(
go.Scatter(x=[1, 2, 3], y=[4, 5, 6]),
row=1, col=1
)
fig.add_trace(
go.Scatter(x=[20, 30, 40], y=[50, 60, 70]),
row=1, col=2
)
fig.update_layout(height=600, width=800,
title_text="Subplots with shared x-axes")
# extra data where xaxis3 is shared with subplot 1
fig.add_trace(go.Scatter(
x=[11, 12, 13],
y=[6, 5, 4],
name="xaxis3 data",
xaxis="x3"
))
# some adjustmentns for xaxis3
fig.update_layout(xaxis3=dict(
title="xaxis3 title",
titlefont=dict(
color="#9467bd"
),
tickfont=dict(
color="#9467bd"
),
anchor="free",
overlaying="x1",
side="right",
position=0.0
))
# extra data where xaxis4 is shared with subplot 2
fig.add_trace(go.Scatter(
x=[50, 60, 70],
y=[60, 60, 60],
name="xaxis4 data",
xaxis="x4",
yaxis = 'y2'
))
# some adjustments for xaxis4
fig.update_layout(xaxis4=dict(
title="xaxis4 title",
titlefont=dict(
color="#9467bd"
),
tickfont=dict(
color="#9467bd"
),
anchor="free",
overlaying="x2",
side="right",
position=0.0
))
# make room to display double x-axes
fig.update_layout(yaxis1=dict(domain=[0.1, 1]),
yaxis2=dict(domain=[0.1, 1]),
)
# not critical, but just to put a little air in there
fig.update_layout(xaxis1=dict(domain=[0.0, 0.4]),
xaxis2=dict(domain=[0.6, 1]),
)
fig.show()
编辑:收紧标题和范围之间的 space。
一种方法是使用 fig.update_layout(title=dict())
:
更改标题本身的位置
fig.update_layout(
title={
'text': "Plot Title",
'y':0.88,
'x':0.42,
'xanchor': 'left',
'yanchor': 'top'})
情节 2
情节 2 的完整代码
from plotly.subplots import make_subplots
import plotly.graph_objects as go
# initial subplot with two traces
fig = make_subplots(rows=1, cols=2)
fig.add_trace(
go.Scatter(x=[1, 2, 3], y=[4, 5, 6]),
row=1, col=1
)
fig.add_trace(
go.Scatter(x=[20, 30, 40], y=[50, 60, 70]),
row=1, col=2
)
fig.update_layout(height=600, width=800,
title_text="Subplots with shared x-axes")
# extra data where xaxis3 is shared with subplot 1
fig.add_trace(go.Scatter(
x=[11, 12, 13],
y=[6, 5, 4],
name="xaxis3 data",
xaxis="x3"
))
# some adjustmentns for xaxis3
fig.update_layout(xaxis3=dict(
title="xaxis3 title",
titlefont=dict(
color="#9467bd"
),
tickfont=dict(
color="#9467bd"
),
anchor="free",
overlaying="x1",
side="right",
position=0.0
))
# extra data where xaxis4 is shared with subplot 2
fig.add_trace(go.Scatter(
x=[50, 60, 70],
y=[60, 60, 60],
name="xaxis4 data",
xaxis="x4",
yaxis = 'y2'
))
# some adjustments for xaxis4
fig.update_layout(xaxis4=dict(
title="xaxis4 title",
titlefont=dict(
color="#9467bd"
),
tickfont=dict(
color="#9467bd"
),
anchor="free",
overlaying="x2",
side="right",
position=0.0
))
# make room to display double x-axes
fig.update_layout(yaxis1=dict(domain=[0.1, 1]),
yaxis2=dict(domain=[0.1, 1]),
)
# not critical, but just to put a little air in there
fig.update_layout(xaxis1=dict(domain=[0.0, 0.4]),
xaxis2=dict(domain=[0.6, 1]),
)
fig.update_layout(
title={
'text': "Plot Title",
'y':0.88,
'x':0.42,
'xanchor': 'left',
'yanchor': 'top'})
fig.show()
这个问题有点棘手,但可行。
There 是如何在单个图中创建多个轴的示例。
基本上,您使用 twinx()
创建另一个轴,然后以这样的方式设置所有内容,使其最终很好地结束。问题是 matplotlib 自动将其他轴放在另一侧(所以 'top'
在 x 轴的情况下, 'right'
在 y- 的情况下轴)。这就是为什么我们需要设置所有这些属性(在哪里显示轴,标签和刻度应该放置在哪个方向)和一些不错的东西,比如标签和刻度的颜色。
import matplotlib.pyplot as plt
fig, ax1 = plt.subplots()
fig.subplots_adjust(right=0.75)
axs =[]
axs.append( ax1 )
for i in range(1,3):
# creates another axes that shares the same y-axis
axs.append( ax1.twiny() )
offest = 42
for i,ax in enumerate(axs):
# sets the ticks to be shown at the bottom
ax.xaxis.tick_bottom()
ax.tick_params(axis='x', direction='out',labelbottom=True)
# places the nex axis (ticks and description) below the other axes
ax.spines["bottom"].set_position(("outward", offest*i)) # additional offset
line1, = axs[0].plot([0, 1, 2], [0, 1, 2], "b-", label="Line 1")
line2, = axs[1].plot([0, 2, 4], [0, 3, 2], "r-", label="Line 2")
line3, = axs[2].plot([0, 10, 60], [50, 30, 15], "g-", label="Line 3")
lines = [line1,line2,line3]
lim = [(0,2), (0,4),(2,65)]
XLabel = ["Time","Distance","Height"]
for i,ax in enumerate(axs):
# set limits
ax.set_xlim( lim[i] )
# set label
ax.set_xlabel( XLabel[i] )
# set label position
ax.xaxis.set_label_position("bottom")
# set label color
color = lines[i].get_color()
ax.xaxis.label.set_color( color )
# set tick color
ax.tick_params(axis='x', colors=color)
# set legend only in one axis (but with all lines)
ax1.legend(lines, [l.get_label() for l in lines])
plt.show()
顺便说一句,由于(我的)方便,我使用了 matplotlib。这是我更喜欢的绘图库,但没有具体原因。
我正在使用 Plotly 并使用共享的 y-axis 和不同的 x-axes 制作散点图子图。我试图使用图形 object (fig['layout'][数据索引]) 语法来显示多个堆叠的 x-axes 及其各自的范围。通过将 'top' 和 'bottom' 分配给图形布局的 side 属性,我只成功地在每个子图中显示了两个 xaxes 和范围。下图中右起第二列应该显示系列 T5、T6 和 T7 的 titles/ranges,但只显示 T5 和 T7 的标题和范围。
是否可以在 Plotly 中的同一个子图中显示超过 2 个 x-axes title/ranges? For an implemented example, Matplotlib supports showing multiple stacked axes
感谢 Vestland,关键是使用图形布局的位置属性并缩放 y-axis 以正确适应调整。基于 Vestland 示例代码的多轴的完整实现,请参见下面的 [monstrosity]。
您需要 make_subplots(rows=1, cols=2)
、add_traces()
和 fig.update_layout(xaxis=dict(domain=...)
的精确组合:
使用
所述包含两条轨迹fig=make_subplots(rows=1, cols=2)
设置一个“常规”子图,并按照 here.使用
添加具有自己的 x 轴的第三条轨迹fig.add_trace(go.Scatter([...[, xaxis="x3"))
然后,调整子图 1 为
xaxis3
腾出空间,使用:fig.update_layout(xaxis3=dict(anchor="free", overlaying="x1", position=0.0))
使用
进行一些最终调整fig.update_layout([...], yaxis2=dict(domain=[0.1, 1]))
之所以要考虑domain
,是因为point 3
中的position
属性不能为负,必须腾出空间对于双 x-axes 不知何故。结果如下:
情节
完整代码:
from plotly.subplots import make_subplots
import plotly.graph_objects as go
# initial subplot with two traces
fig = make_subplots(rows=1, cols=2)
fig.add_trace(
go.Scatter(x=[1, 2, 3], y=[4, 5, 6]),
row=1, col=1
)
fig.add_trace(
go.Scatter(x=[20, 30, 40], y=[50, 60, 70]),
row=1, col=2
)
fig.update_layout(height=600, width=800,
title_text="Subplots with shared x-axes")
# extra data where xaxis3 is shared with subplot 1
fig.add_trace(go.Scatter(
x=[11, 12, 13],
y=[6, 5, 4],
name="xaxis3 data",
xaxis="x3"
))
# some adjustmentns for xaxis3
fig.update_layout(xaxis3=dict(
title="xaxis3 title",
titlefont=dict(
color="#9467bd"
),
tickfont=dict(
color="#9467bd"
),
anchor="free",
overlaying="x1",
side="right",
position=0.0
))
# extra data where xaxis4 is shared with subplot 2
fig.add_trace(go.Scatter(
x=[50, 60, 70],
y=[60, 60, 60],
name="xaxis4 data",
xaxis="x4",
yaxis = 'y2'
))
# some adjustments for xaxis4
fig.update_layout(xaxis4=dict(
title="xaxis4 title",
titlefont=dict(
color="#9467bd"
),
tickfont=dict(
color="#9467bd"
),
anchor="free",
overlaying="x2",
side="right",
position=0.0
))
# make room to display double x-axes
fig.update_layout(yaxis1=dict(domain=[0.1, 1]),
yaxis2=dict(domain=[0.1, 1]),
)
# not critical, but just to put a little air in there
fig.update_layout(xaxis1=dict(domain=[0.0, 0.4]),
xaxis2=dict(domain=[0.6, 1]),
)
fig.show()
编辑:收紧标题和范围之间的 space。
一种方法是使用 fig.update_layout(title=dict())
:
fig.update_layout(
title={
'text': "Plot Title",
'y':0.88,
'x':0.42,
'xanchor': 'left',
'yanchor': 'top'})
情节 2
情节 2 的完整代码
from plotly.subplots import make_subplots
import plotly.graph_objects as go
# initial subplot with two traces
fig = make_subplots(rows=1, cols=2)
fig.add_trace(
go.Scatter(x=[1, 2, 3], y=[4, 5, 6]),
row=1, col=1
)
fig.add_trace(
go.Scatter(x=[20, 30, 40], y=[50, 60, 70]),
row=1, col=2
)
fig.update_layout(height=600, width=800,
title_text="Subplots with shared x-axes")
# extra data where xaxis3 is shared with subplot 1
fig.add_trace(go.Scatter(
x=[11, 12, 13],
y=[6, 5, 4],
name="xaxis3 data",
xaxis="x3"
))
# some adjustmentns for xaxis3
fig.update_layout(xaxis3=dict(
title="xaxis3 title",
titlefont=dict(
color="#9467bd"
),
tickfont=dict(
color="#9467bd"
),
anchor="free",
overlaying="x1",
side="right",
position=0.0
))
# extra data where xaxis4 is shared with subplot 2
fig.add_trace(go.Scatter(
x=[50, 60, 70],
y=[60, 60, 60],
name="xaxis4 data",
xaxis="x4",
yaxis = 'y2'
))
# some adjustments for xaxis4
fig.update_layout(xaxis4=dict(
title="xaxis4 title",
titlefont=dict(
color="#9467bd"
),
tickfont=dict(
color="#9467bd"
),
anchor="free",
overlaying="x2",
side="right",
position=0.0
))
# make room to display double x-axes
fig.update_layout(yaxis1=dict(domain=[0.1, 1]),
yaxis2=dict(domain=[0.1, 1]),
)
# not critical, but just to put a little air in there
fig.update_layout(xaxis1=dict(domain=[0.0, 0.4]),
xaxis2=dict(domain=[0.6, 1]),
)
fig.update_layout(
title={
'text': "Plot Title",
'y':0.88,
'x':0.42,
'xanchor': 'left',
'yanchor': 'top'})
fig.show()
这个问题有点棘手,但可行。
There 是如何在单个图中创建多个轴的示例。
基本上,您使用 twinx()
创建另一个轴,然后以这样的方式设置所有内容,使其最终很好地结束。问题是 matplotlib 自动将其他轴放在另一侧(所以 'top'
在 x 轴的情况下, 'right'
在 y- 的情况下轴)。这就是为什么我们需要设置所有这些属性(在哪里显示轴,标签和刻度应该放置在哪个方向)和一些不错的东西,比如标签和刻度的颜色。
import matplotlib.pyplot as plt
fig, ax1 = plt.subplots()
fig.subplots_adjust(right=0.75)
axs =[]
axs.append( ax1 )
for i in range(1,3):
# creates another axes that shares the same y-axis
axs.append( ax1.twiny() )
offest = 42
for i,ax in enumerate(axs):
# sets the ticks to be shown at the bottom
ax.xaxis.tick_bottom()
ax.tick_params(axis='x', direction='out',labelbottom=True)
# places the nex axis (ticks and description) below the other axes
ax.spines["bottom"].set_position(("outward", offest*i)) # additional offset
line1, = axs[0].plot([0, 1, 2], [0, 1, 2], "b-", label="Line 1")
line2, = axs[1].plot([0, 2, 4], [0, 3, 2], "r-", label="Line 2")
line3, = axs[2].plot([0, 10, 60], [50, 30, 15], "g-", label="Line 3")
lines = [line1,line2,line3]
lim = [(0,2), (0,4),(2,65)]
XLabel = ["Time","Distance","Height"]
for i,ax in enumerate(axs):
# set limits
ax.set_xlim( lim[i] )
# set label
ax.set_xlabel( XLabel[i] )
# set label position
ax.xaxis.set_label_position("bottom")
# set label color
color = lines[i].get_color()
ax.xaxis.label.set_color( color )
# set tick color
ax.tick_params(axis='x', colors=color)
# set legend only in one axis (but with all lines)
ax1.legend(lines, [l.get_label() for l in lines])
plt.show()
顺便说一句,由于(我的)方便,我使用了 matplotlib。这是我更喜欢的绘图库,但没有具体原因。