You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Plotly中根据X轴范围滑块自动缩放Y轴?

实现Plotly时间序列滑块选中后自动缩放Y轴

要让Y轴随X轴选中的日期范围自动缩放,需调整Y轴配置并添加交互逻辑,以下是两种可行方案:

方案1:纯Plotly Python(添加JavaScript回调)

在现有代码基础上,通过JavaScript监听X轴范围变化事件,实时计算并更新Y轴范围:

import plotly.graph_objects as go
import pandas as pd
import webbrowser

# 加载并预处理数据
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv")
df.columns = [col.replace("AAPL.", "") for col in df.columns]
df['Date'] = pd.to_datetime(df['Date'])

# 创建图表
fig = go.Figure(go.Scatter(x=df.Date, y=df.High))

# 配置布局
fig.update_layout(
    title_text="时间序列(带范围滑块与Y轴自动缩放)",
    xaxis={
        "rangeselector": {
            "buttons": [
                {"count":1, "label":"1m", "step":"month", "stepmode":"backward"},
                {"count":6, "label":"6m", "step":"month", "stepmode":"backward"},
                {"count":1, "label":"YTD", "step":"year", "stepmode":"todate"},
                {"count":1, "label":"1y", "step":"year", "stepmode":"backward"},
                {"step":"all"}
            ]
        },
        "rangeslider": {"visible": True},
        "type": "date"
    },
    yaxis={"autorange": True, "fixedrange": False}  # 允许Y轴动态调整范围
)

# 添加JavaScript回调逻辑
js_code = """
<script>
const plotDiv = document.getElementById('plotly-chart');
plotDiv.addEventListener('plotly_relayout', (event) => {
    const { 'xaxis.range[0]': xStart, 'xaxis.range[1]': xEnd } = event.detail;
    if (xStart && xEnd) {
        const startDate = new Date(xStart);
        const endDate = new Date(xEnd);
        const trace = plotDiv.data[0];
        const filteredY = trace.y.filter((_, idx) => {
            const date = new Date(trace.x[idx]);
            return date >= startDate && date <= endDate;
        });
        const yMin = Math.min(...filteredY);
        const yMax = Math.max(...filteredY);
        const padding = (yMax - yMin) * 0.05;  // 添加5%边距避免数据贴边
        Plotly.relayout(plotDiv, { 'yaxis.range': [yMin - padding, yMax + padding] });
    }
});
</script>
"""

# 生成HTML并注入回调代码
html_content = fig.to_html(full_html=True, include_plotlyjs='cdn')
html_content = html_content.replace('</body>', js_code + '</body>')

# 保存并打开HTML文件
with open('auto_scale_y_chart.html', 'w') as f:
    f.write(html_content)
webbrowser.open('auto_scale_y_chart.html')

方案2:使用Dash(简洁的Python回调)

若允许使用Dash框架,可利用其内置回调机制快速实现:

import dash
from dash import dcc, html, Input, Output
import plotly.graph_objects as go
import pandas as pd

# 加载数据
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv")
df.columns = [col.replace("AAPL.", "") for col in df.columns]
df['Date'] = pd.to_datetime(df['Date'])

# 初始化Dash应用
app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Graph(id='time-series-chart')
])

@app.callback(
    Output('time-series-chart', 'figure'),
    Input('time-series-chart', 'relayoutData')
)
def update_y_range(relayout_data):
    # 创建基础图表
    fig = go.Figure(go.Scatter(x=df.Date, y=df.High))
    fig.update_layout(
        title_text="时间序列(带范围滑块与Y轴自动缩放)",
        xaxis={
            "rangeselector": {
                "buttons": [
                    {"count":1, "label":"1m", "step":"month", "stepmode":"backward"},
                    {"count":6, "label":"6m", "step":"month", "stepmode":"backward"},
                    {"count":1, "label":"YTD", "step":"year", "stepmode":"todate"},
                    {"count":1, "label":"1y", "step":"year", "stepmode":"backward"},
                    {"step":"all"}
                ]
            },
            "rangeslider": {"visible": True},
            "type": "date"
        }
    )

    # 根据X轴选中范围调整Y轴
    if relayout_data and 'xaxis.range[0]' in relayout_data and 'xaxis.range[1]' in relayout_data:
        x_start = pd.to_datetime(relayout_data['xaxis.range[0]'])
        x_end = pd.to_datetime(relayout_data['xaxis.range[1]'])
        filtered_df = df[(df['Date'] >= x_start) & (df['Date'] <= x_end)]
        y_min, y_max = filtered_df['High'].min(), filtered_df['High'].max()
        padding = (y_max - y_min) * 0.05
        fig.update_yaxes(range=[y_min - padding, y_max + padding])
    else:
        fig.update_yaxes(autorange=True)
    
    return fig

if __name__ == '__main__':
    app.run_server(debug=True)

核心要点

  • 方案1无需额外框架,通过原生JS实现交互,适合纯Plotly静态场景。
  • 方案2用Dash的Python回调处理逻辑,代码更易维护,适合构建交互式Web应用。

内容的提问来源于stack exchange,提问作者Devendra Yadav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 12:51:17