Plotly : 동일한 서브 플롯에 2 개 이상의 x 축 제목 / 범위를 표시하는 방법은 무엇입니까?

Nov 28 2020

Plotly를 사용하고 공유 y 축과 다른 x 축을 사용하여 산점도 하위 플롯을 만들고 있습니다. 그림 개체 (fig [ 'layout'] [data index]) 구문을 사용하여 여러 누적 x 축과 해당 범위를 표시하려고했습니다. 그림 레이아웃의 측면 속성에 '상단'과 '하단'을 할당하여 서브 플롯 당 두 개의 x 축과 범위를 표시하는 데 성공했습니다. 아래 그림의 오른쪽에서 두 번째 열에는 시리즈 T5, T6 및 T7의 제목 / 범위가 표시되지만 T5 및 T7의 제목과 범위 만 표시됩니다.

Plotly의 동일한 서브 플롯에 2 개 이상의 x 축 제목 / 범위를 표시 할 수 있습니까? 구현 된 예제의 경우 Matplotlib는 다중 누적 축 표시를 지원합니다.

Vestland에 감사드립니다. 핵심은 Figure의 레이아웃의 위치 속성을 사용하고 조정에 맞게 y 축을 조정하는 것이 었습니다. Vestland의 샘플 코드를 기반으로 한 다중 축의 전체 구현은 아래 [괴물]을 참조하십시오.

답변

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. 다음을 사용하여 자체 x 축으로 세 번째 트레이스를 추가합니다. 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()

편집 : 제목과 범위 사이의 공간을 좁 힙니다.

한 가지 방법은 다음을 사용하여 제목 자체의 위치를 ​​변경하는 것입니다 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

질문은 약간 까다 롭지 만 실행 가능합니다. 단일 플롯에 여러 축을 생성하는 방법에 대한 예가 있습니다 . 기본적으로 다른 축을 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()

BTW, 나는 (내) 편의성 때문에 matplotlib를 사용했습니다 . 내가 선호하는 플로팅 라이브러리이지만 특별한 이유는 없습니다.