Plotly: Wie werden mehr als 2 x-Achsen-Titel / Bereiche in derselben Unterzeichnung angezeigt?

Nov 28 2020

Ich verwende Plotly und erstelle Streudiagramm-Unterplots mit einer gemeinsamen y-Achse und verschiedenen x-Achsen. Ich habe versucht, die Syntax des Figurenobjekts (fig ['layout'] [Datenindex]) zu verwenden, um mehrere gestapelte x-Achsen und ihre jeweiligen Bereiche anzuzeigen. Es ist mir nur gelungen, zwei x-Achsen und Bereiche pro Teilplot anzuzeigen, indem ich dem Seitenattribut des Figurenlayouts 'oben' und 'unten' zugewiesen habe. In der zweiten Spalte von rechts in der folgenden Abbildung sollten Titel / Bereiche für die Serien T5, T6 und T7 angezeigt werden, es werden jedoch nur Titel und Bereich für T5 und T7 angezeigt.

Ist es möglich, in Plotly mehr als 2 Titel / Bereiche mit x Achsen in derselben Nebenhandlung anzuzeigen? In einem implementierten Beispiel unterstützt Matplotlib das Anzeigen mehrerer gestapelter Achsen

Vielen Dank an Vestland. Der Schlüssel bestand darin, das Positionsattribut des Layouts der Figur zu verwenden und die y-Achse zu skalieren, um die Anpassung richtig anzupassen. In der folgenden [Monstrosität] finden Sie eine vollständige Implementierung mehrerer Achsen basierend auf dem Beispielcode von Vestland.

Antworten

2 vestland Nov 29 2020 at 22:47

Sie benötigen eine genaue Kombination aus make_subplots(rows=1, cols=2), add_traces()und fig.update_layout(xaxis=dict(domain=...):

  1. Richten Sie eine "reguläre" Nebenhandlung ein fig=make_subplots(rows=1, cols=2)und verwenden Sie zwei Spuren, wie hier beschrieben .

  2. Fügen Sie eine dritte Spur mit einer eigenen X-Achse hinzu fig.add_trace(go.Scatter([...[, xaxis="x3"))

  3. Passen Sie dann Teilplot 1 an, um Platz für Folgendes zu schaffen xaxis3:fig.update_layout(xaxis3=dict(anchor="free", overlaying="x1", position=0.0))

  4. Nehmen Sie einige letzte Anpassungen mit vor fig.update_layout([...], yaxis2=dict(domain=[0.1, 1]))

Der Grund, warum Sie dies domainberücksichtigen müssen, ist, dass das positionAttribut in point 3nicht negativ sein kann und Sie irgendwie Platz für die doppelten x-Achsen schaffen müssen. Hier ist das Ergebnis:

Handlung

Vollständiger Code:

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()

Bearbeiten: Verschließen Sie den Abstand zwischen Titel und Bereich.

Ein Ansatz besteht darin, die Position des Titels selbst zu ändern, indem Sie Folgendes verwenden fig.update_layout(title=dict()):

fig.update_layout(
    title={
        'text': "Plot Title",
        'y':0.88,
        'x':0.42,
        'xanchor': 'left',
        'yanchor': 'top'})

Grundstück 2

Vollständiger Code für Grundstück 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()
1 max Nov 30 2020 at 08:30

Die Frage ist etwas knifflig, aber machbar. Es gibt ein Beispiel für das Erstellen mehrerer Achsen in einem einzelnen Diagramm. Grundsätzlich erstellen Sie eine andere Achse mit twinx()und stellen dann alles so ein, dass es gut endet. Das Problem ist, dass matplotlib automatisch andere Achsen auf der gegenüberliegenden Seite platziert (also 'top'im Fall der x-Achse und 'right'im Fall der y-Achse). Aus diesem Grund müssen wir alle diese Eigenschaften (wo die Achse angezeigt werden soll, in welche Richtung das Etikett und die Häkchen platziert werden sollen) und einige nette Dinge festlegen, wie z. B. die Farbe des Etiketts und der Häkchen.

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()

Übrigens habe ich Matplotlib aus (meiner) Bequemlichkeit verwendet. Es ist die Plotbibliothek, die ich bevorzuge, aber ohne besonderen Grund.