Plotly: Comment afficher plus de 2 titres / plages d'axes x sur la même sous-parcelle?
J'utilise Plotly et je crée des sous-graphiques de nuage de points avec un axe y partagé et différents axes x. J'ai essayé d'utiliser la syntaxe de l'objet figure (fig ['layout'] [data index]) pour afficher plusieurs axes x empilés et leurs plages respectives. J'ai seulement réussi à montrer deux xaxes et plages par sous-graphique en attribuant «haut» et «bas» à l'attribut latéral de la mise en page de la figure. La deuxième colonne à partir de la droite de la figure ci-dessous doit afficher les titres / plages pour les séries T5, T6 et T7, mais seuls le titre et la plage pour T5 et T7 apparaissent.
Est-il possible d'afficher plus de 2 titres / plages d'axes x sur la même sous-parcelle dans Plotly? Pour un exemple implémenté, Matplotlib prend en charge l'affichage de plusieurs axes empilés

Merci à Vestland, la clé était d'utiliser l'attribut de position de la mise en page de la figure et de mettre à l'échelle l'axe des y pour s'adapter correctement à l'ajustement. Voir la [monstruosité] ci-dessous pour une implémentation complète de plusieurs axes basés sur l'exemple de code de Vestland.

Réponses
Vous aurez besoin d'une combinaison précise de make_subplots(rows=1, cols=2)
, add_traces()
et fig.update_layout(xaxis=dict(domain=...)
:
Configurez un sous-tracé «régulier» en utilisant
fig=make_subplots(rows=1, cols=2)
et incluez deux traces comme décrit ici .Ajoutez une troisième trace avec sa propre xaxis en utilisant
fig.add_trace(go.Scatter([...[, xaxis="x3"))
Ensuite, ajustez la sous-parcelle 1 pour faire de la place pour
xaxis3
utiliser:fig.update_layout(xaxis3=dict(anchor="free", overlaying="x1", position=0.0))
Faites quelques ajustements finaux en utilisant
fig.update_layout([...], yaxis2=dict(domain=[0.1, 1]))
La raison pour laquelle vous devrez prendre domain
en compte est que l' position
attribut dans point 3
ne peut pas être négatif et que vous devrez faire de la place pour les doubles axes x. Voici le résultat:
Terrain

Code complet:
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()
Modifier: resserrez l'espace entre le titre et la plage.
Une approche consiste à changer la position du titre lui-même en utilisant fig.update_layout(title=dict())
:
fig.update_layout(
title={
'text': "Plot Title",
'y':0.88,
'x':0.42,
'xanchor': 'left',
'yanchor': 'top'})
Parcelle 2

Code complet pour Plot 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()
La question est un peu délicate mais faisable. Il existe un exemple de création de plusieurs axes dans un même tracé. Fondamentalement, vous créez un autre axe avec twinx()
, puis définissez tout de manière à ce que cela se termine bien. Le problème est que matplotlib place automatiquement les autres axes du côté opposé (donc 'top'
dans le cas de l'axe des x et 'right'
dans le cas de l'axe des y). C'est pourquoi nous devons définir toutes ces propriétés (où afficher l'axe, dans quelle direction l'étiquette et les coches doivent-elles être placées) et quelques jolies choses, telles que la couleur de l'étiquette et les coches.
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()

BTW, j'ai utilisé matplotlib en raison de (ma) commodité. C'est la bibliothèque de traçage que je préfère mais sans raison spécifique.