解决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)
关键修改点说明
用
dcc.Store保存数据集状态- 摒弃全局
df变量,改用dcc.Store存储当前数据的JSON格式,确保每次操作基于最新数据集,适配Dash的无状态特性。
- 摒弃全局
调整删除触发逻辑
- 将删除操作触发源从
selectedData改为按钮点击,符合用户“选点→点击删除”的操作逻辑,避免选点时自动触发删除。
- 将删除操作触发源从
正确处理索引映射
pointIndex是当前图表数据的位置(iloc),而非DataFrame的行标签(index)。删除时先通过df.iloc[selected_positions].index获取对应行索引,再执行删除,避免因索引不连续导致的错误。
回调参数优化
- 添加
prevent_initial_call=True避免应用启动时触发删除回调;同步更新图表和存储的数据集,保证状态一致性。
- 添加
内容的提问来源于stack exchange,提问作者Henrique Schinaider
相关产品推荐
相关产品推荐

