【问题标题】:Plot one series with two y-axes in Plotly在 Plotly 中用两个 y 轴绘制一个系列
【发布时间】:2020-12-14 14:11:03
【问题描述】:

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

我正在分析一些 Strava 数据,并绘制了平均速度与距离的关系图。我希望右侧的另一个 y 轴显示等效速度(1/速度)。 我已经阅读并搜索过,但只找到了如何在多个 y 轴上绘制多个 series 的示例,而不是在两个 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()

【问题讨论】:

  • 我尝试过使用您的示例(即使用 None 作为跟踪等),但运气不佳。但是,如果只是这些值对您很重要,而不是第二个 y 轴,您可以为text 参数添加变量y2,如下go.Scatter(x=xx, y=y1, text=y2)。当该点悬停在上面时,这将以分钟/英里为单位向您显示速度。
  • 在 Plotly 中执行此操作可能很棘手,因为第二个 y 轴不是线性的。一种解决方法是将整数步速 8, 9, ... , 12 添加为注释,将它们放置在绘图上应位于的位置

标签: plotly yaxis


【解决方案1】:

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

一种解决方法是使用注释,将整数步速 [8,9,10,11,12] 放置在 线性刻度 上(例如,8 分钟/英里的步速应位于 y 坐标 60 /8 = 7.5, ..., 12 min/mile 应位于 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, 9, 10, 11, 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, xref="paper", yref="y", 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()

【讨论】:

    猜你喜欢
    • 2021-11-13
    • 2017-07-14
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 2014-07-10
    • 2019-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多