Plotly: Bagaimana cara menampilkan lebih dari 2 judul / rentang sumbu x pada subplot yang sama?

Nov 28 2020

Saya menggunakan Plotly dan membuat subplot sebar dengan sumbu y bersama dan sumbu x yang berbeda. Saya telah mencoba menggunakan sintaks objek gambar (fig ['layout'] [indeks data]) untuk menampilkan beberapa sumbu x yang ditumpuk dan rentangnya masing-masing. Saya hanya berhasil menampilkan dua xax dan rentang per subplot dengan menetapkan 'top' dan 'bottom' ke atribut samping dari tata letak gambar. Kolom ke-2 dari kanan pada gambar di bawah ini harus menunjukkan judul / rentang untuk seri T5, T6, dan T7 tetapi hanya judul dan rentang untuk T5 dan T7 yang muncul.

Apakah mungkin untuk menampilkan lebih dari 2 judul / rentang sumbu x pada subplot yang sama di Plotly? Untuk contoh yang diimplementasikan, Matplotlib mendukung menampilkan beberapa sumbu bertumpuk

Terima kasih kepada Vestland, kuncinya adalah menggunakan atribut posisi dari tata letak gambar dan menskalakan sumbu y agar sesuai dengan penyesuaian. Lihat [monstrositas] di bawah untuk implementasi penuh dari banyak sumbu berdasarkan kode sampel Vestland.

Jawaban

2 vestland Nov 29 2020 at 22:47

Anda akan membutuhkan kombinasi yang tepat dari make_subplots(rows=1, cols=2), add_traces()dan fig.update_layout(xaxis=dict(domain=...):

  1. Siapkan subplot "biasa" menggunakan fig=make_subplots(rows=1, cols=2)dan sertakan dua jejak seperti yang dijelaskan di sini .

  2. Tambahkan jejak ketiga dengan xaxisnya sendiri menggunakan fig.add_trace(go.Scatter([...[, xaxis="x3"))

  3. Kemudian, sesuaikan subplot 1 untuk memberi ruang bagi xaxis3penggunaan:fig.update_layout(xaxis3=dict(anchor="free", overlaying="x1", position=0.0))

  4. Buat beberapa penyesuaian terakhir menggunakan fig.update_layout([...], yaxis2=dict(domain=[0.1, 1]))

Alasan mengapa Anda harus domainmemperhitungkannya adalah karena positionatribut di point 3tidak boleh negatif, dan Anda harus memberi ruang untuk sumbu x ganda. Inilah hasilnya:

Merencanakan

Kode lengkap:

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

Edit: Kencangkan jarak antara judul dan rentang.

Salah satu pendekatannya adalah dengan mengubah posisi judul itu sendiri menggunakan fig.update_layout(title=dict()):

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

Plot 2

Kode lengkap untuk 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()
1 max Nov 30 2020 at 08:30

Pertanyaannya agak rumit tapi bisa dilakukan. Ada contoh cara membuat banyak sumbu dalam satu plot. Pada dasarnya, Anda membuat sumbu lain dengan twinx()dan kemudian mengatur semuanya sedemikian rupa sehingga berakhir dengan baik. Masalahnya adalah matplotlib secara otomatis menempatkan sumbu lain di sisi yang berlawanan (jadi 'top'dalam kasus sumbu x dan 'right'dalam kasus sumbu y). Inilah mengapa kita perlu mengatur semua properti ini (di mana harus menunjukkan sumbu, ke arah mana label dan tanda centang ditempatkan) dan beberapa hal bagus, seperti warna label dan tanda centang.

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, saya menggunakan matplotlib karena kenyamanan (saya). Ini adalah perpustakaan plot yang saya sukai tetapi tanpa alasan khusus.