在Plotly中用两个y轴绘制一个系列

问题描述

我正在尝试使用Plotly绘制一组具有两个不同y轴的数据。看来应该有一个简单的答案,但到目前为止我一直没有成功...

我正在分析一些Strava数据,并绘制了平均速度与距离的关系图。我希望右侧的另一个y轴显示等效的速度(1 /速度)。 我已经阅读和搜索过,但是只找到了如何在多个y轴上绘制多个系列的示例,而不是在两个y轴上绘制一个序列的示例。我发现一些笨拙的解决方法,建议绘制两条迹线并手动设置yrange等。但这似乎很容易做到。

对于具体的操作,这是使用matplotlib的预期结果的示例。 请注意,我们只绘制一次数据,但是使用函数在次要y轴上设置刻度。像这样的东西存在吗?

import matplotlib.pyplot as plt

xx = [1,2,3,4]
y1 = [8,7,6,5]
y2 = [60. / y for y in y1]  # min/mile

fig,ax = plt.subplots()

ax.plot(xx,y1)
ax.set_ylabel('speed (miles/hr)')
ax.set_xlabel('distance (miles)')


def spd2pac(y):
    return 60. / y


def pac2spd(y):
    return 60. / y


secax = ax.secondary_yaxis('right',functions=(spd2pac,pac2spd))
secax.set_ylabel('pace (min/mile)')
plt.show()

desired result with matplotlib

解决方法

主要困难是第二个y轴不是线性的。据我所知,Plotly无法添加第二个y轴并指定非线性比例(这不是以10为底的对数比例)。

一种解决方法是使用注释,将整数步速[8,9,10,11,12]放置在它们以线性标尺的位置(例如,8分钟/英里的步速应位于y-坐标60/8 = 7.5,...,12分钟/英里应位于y坐标60/12 = 5),从而在次要y轴上显示刻度线。您也可以添加辅助y轴标题作为注释,以避免重叠注释刻度线。

但是,这纯粹是视觉上的,如果您想包括步速信息,可以按照@Jacob K的建议将它们添加为悬停模板的一部分。

import plotly.graph_objects as go
from plotly.subplots import make_subplots

xx = [1,2,3,4]
y1 = [8,7,6,5]
y2 = [60. / y for y in y1]  # min/mile

fig = make_subplots(specs=[[{"secondary_y": True}]])

fig.add_trace(
    go.Scatter(
        x=xx,y=y1,marker_color="Blue",name="speed"
    )
)

fig.add_trace(
    go.Scatter(
        x=None,y=None,),secondary_y=True
)

paces = [8,12]
y_coordinate = [60. / y for y in paces]

# hardcoded the x value
yaxes_dict = [dict(x=0.955,y=y_coordinate[idx],xref="paper",yref="y",text=str(y_val),showarrow=False) for idx,y_val in enumerate(paces)]
yaxes_title = [dict(x=0.97,y=6.5,text='pace (min/mile)',textangle=-90,showarrow=False)]
fig.update_layout(annotations=yaxes_dict + yaxes_title)

fig['layout']['yaxis2'].update(ticks='',showticklabels=False)
fig['layout']['yaxis'].update(title='speed (miles/hour)')

fig.show()

enter image description here