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

解决Dash中LassoSelector删除散点时的索引错误问题

解决Dash+Plotly LassoSelector删除散点图点时的索引错误问题

修正后的完整代码

import dash
from dash import dcc, html, Input, Output, State, callback
import plotly.graph_objs as go
import pandas as pd
import json

# 初始化原始数据
initial_df = pd.DataFrame({
    'x': [1,2,3,4,5],
    'y': [1, 4, 9, 16, 25]
})

app = dash.Dash(__name__)

app.layout = html.Div(children=[
    html.H1(children='Grafico de Dispersão'),
    dcc.Graph(
        id='scatter-graph',
        figure=go.Figure(
            data=[go.Scatter(x=initial_df['x'], y=initial_df['y'], mode='markers')],
            layout=go.Layout(
                title='Grafico Teste',
                xaxis={'title': 'Eixo X'},
                yaxis={'title': 'Eixo Y'}
            )
        )
    ),
    html.Div(id='selected-points'),
    html.Button('Excluir pontos selecionados', id='delete-selected-points'),
    # 用dcc.Store保存当前数据集,避免全局变量问题
    dcc.Store(id='current-data', data=initial_df.to_json(orient='split'))
])

@callback(
    Output('selected-points', 'children'),
    Input('scatter-graph', 'selectedData'),
    State('current-data', 'data')
)
def update_selected_points(selectedData, current_data):
    if selectedData is None:
        return 'Nenhum ponto foi selecionado'
    else:
        df = pd.read_json(current_data, orient='split')
        # pointIndex是当前图表中数据的位置,对应df的iloc位置
        indices = [point['pointIndex'] for point in selectedData['points']]
        selected_points = df.iloc[indices]
        return f'Pontos selecionados: {selected_points.to_dict("records")}'

@callback(
    Output('scatter-graph', 'figure'),
    Output('current-data', 'data'),
    Input('delete-selected-points', 'n_clicks'),
    State('scatter-graph', 'selectedData'),
    State('current-data', 'data'),
    prevent_initial_call=True
)
def delete_selected_points(n_clicks, selectedData, current_data):
    if selectedData is None:
        # 没有选点,返回当前图表和数据
        df = pd.read_json(current_data, orient='split')
        fig = go.Figure(data=[go.Scatter(x=df['x'], y=df['y'], mode='markers')])
        fig.update_layout(title='Grafico Teste', xaxis_title='Eixo X', yaxis_title='Eixo Y')
        return fig, current_data
    
    df = pd.read_json(current_data, orient='split')
    # 获取选中点在当前df中的位置(iloc),转换为对应的行索引(index)
    selected_positions = [point['pointIndex'] for point in selectedData['points']]
    # 获取这些位置对应的行索引
    indices_to_drop = df.iloc[selected_positions].index.tolist()
    # 删除指定索引的行
    new_df = df.drop(indices_to_drop)
    
    # 生成新图表
    new_fig = go.Figure(data=[go.Scatter(x=new_df['x'], y=new_df['y'], mode='markers')])
    new_fig.update_layout(title='Grafico Teste', xaxis_title='Eixo X', yaxis_title='Eixo Y')
    
    return new_fig, new_df.to_json(orient='split')

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

关键修改点说明

  1. 用dcc.Store保存数据集状态

    • 摒弃全局df变量,改用dcc.Store存储当前数据的JSON格式,确保每次操作基于最新数据集,适配Dash的无状态特性。
  2. 调整删除触发逻辑

    • 将删除操作触发源从selectedData改为按钮点击,符合用户“选点→点击删除”的操作逻辑,避免选点时自动触发删除。
  3. 正确处理索引映射

    • pointIndex是当前图表数据的位置(iloc),而非DataFrame的行标签(index)。删除时先通过df.iloc[selected_positions].index获取对应行索引,再执行删除,避免因索引不连续导致的错误。
  4. 回调参数优化

    • 添加prevent_initial_call=True避免应用启动时触发删除回调;同步更新图表和存储的数据集,保证状态一致性。

内容的提问来源于stack exchange,提问作者Henrique Schinaider

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 00:57:28