プロット:同じサブプロットに3つ以上のx軸のタイトル/範囲を表示するにはどうすればよいですか?

Nov 28 2020

私はPlotlyを使用しており、共有のy軸と異なるx軸を使用して散布図のサブプロットを作成しています。私は、figureオブジェクト(fig ['layout'] [data index])構文を使用して、複数のスタックされたx軸とそれぞれの範囲を表示しようとしました。フィギュアレイアウトのside属性に「top」と「bottom」を割り当てることによって、サブプロットごとに2つのxaxと範囲を表示することに成功しただけです。下の図の右から2番目の列には、シリーズT5、T6、およびT7のタイトル/範囲が表示されますが、T5およびT7のタイトルと範囲のみが表示されます。

Plotlyの同じサブプロットに2つ以上のx軸のタイトル/範囲を表示することは可能ですか?実装例として、Matplotlibは複数のスタック軸の表示をサポートしています

Vestlandのおかげで、重要なのは、フィギュアのレイアウトの位置属性を使用し、調整に適切に合うようにy軸をスケーリングすることでした。Vestlandのサンプルコードに基づく複数の軸の完全な実装については、以下の[monstrosity]を参照してください。

回答

2 vestland Nov 29 2020 at 22:47

あなたはの正確な組み合わせが必要になりますmake_subplots(rows=1, cols=2)add_traces()fig.update_layout(xaxis=dict(domain=...)

  1. ここでfig=make_subplots(rows=1, cols=2)説明するように、を使用して「通常の」サブプロットを設定し、2つのトレースを含めます。

  2. を使用して独自のxaxisで3番目のトレースを追加します fig.add_trace(go.Scatter([...[, xaxis="x3"))

  3. 次に、サブプロット1を調整して、以下xaxis3を使用するためのスペースを作ります。fig.update_layout(xaxis3=dict(anchor="free", overlaying="x1", position=0.0))

  4. を使用していくつかの最終調整を行います fig.update_layout([...], yaxis2=dict(domain=[0.1, 1]))

あなたが取る必要があります理由domainため、アカウントには、position内の属性point 3缶が負になることはない、とあなたは何とかダブルx軸用のスペースを確保する必要があります。結果は次のとおりです。

プロット

完全なコード:

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

編集:タイトルと範囲の間のスペースを締めます。

1つのアプローチは、以下を使用してタイトル自体の位置を変更することです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()
1 max Nov 30 2020 at 08:30

質問は少しトリッキーですが、実行可能です。1つのプロットに複数の軸を作成する方法の例があります。基本的には、で別の軸を作成し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を使用しました。私が好むのはプロットライブラリですが、特別な理由はありません。