Plotly: Bagaimana cara menampilkan lebih dari 2 judul / rentang sumbu x pada subplot yang sama?
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
Anda akan membutuhkan kombinasi yang tepat dari make_subplots(rows=1, cols=2), add_traces()dan fig.update_layout(xaxis=dict(domain=...):
Siapkan subplot "biasa" menggunakan
fig=make_subplots(rows=1, cols=2)dan sertakan dua jejak seperti yang dijelaskan di sini .Tambahkan jejak ketiga dengan xaxisnya sendiri menggunakan
fig.add_trace(go.Scatter([...[, xaxis="x3"))Kemudian, sesuaikan subplot 1 untuk memberi ruang bagi
xaxis3penggunaan:fig.update_layout(xaxis3=dict(anchor="free", overlaying="x1", position=0.0))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()
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.