如何包含破折号地图工具来更新破折号数据表?

问题描述 投票:0回答:1

我下面有一个破折号应用程序。 目前,只要用户单击地图上的点,该应用程序就会更新破折号数据表。我对如何使用破折号地图工具(框选择和套索选择)来更新表格(也保留单击功能)有一点了解。 我尝试添加一个新的回调,其中包括破折号工具的“selecteddata”函数,但它似乎停止了所有以前的回调。

import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import plotly.graph_objs as go
import dash_bootstrap_components as dbc
import pandas as pd
from dash import dash_table



pd.options.mode.chained_assignment = None  # default='warn'


df = pd.read_csv('Data1.csv')


app = dash.Dash(external_stylesheets=[dbc.themes.SLATE])

app.title = "Project 1"

server = app.server



color = {'Mixed': '#e48900',
         'Arable': '#5aa469',
         'Livestock': '#8ab6d6'}

def update_bar(df):
    fig = go.Figure()
    for type in df['Type'].unique():
        df_by_Type = df[df['Type']==type]
        df_by_Type.sort_values('Capacity',inplace=True)
        fig.add_trace(go.Bar({
                              'x':df_by_Type['Capacity'],
                              'y':df_by_Type['Name'],
                              'orientation':'h',
                              'name':type,
                              'marker':{'color':color[type]},
                              # 'cumulative':{'enabled':True,'direction':'decreasing'}
                              # 'histfunc':'count'
        }))

    fig.update_layout(barmode='stack',height=900)
    fig.update_yaxes(categoryorder='category descending')
    fig.update_xaxes(title_text='Hectares')

    return fig

def update_map(df):
    traces = []

    for type in df['Type'].unique():
       
        traces.append(go.Scattermapbox(
        lat=df['Latitude'],
        lon=df['Longitude'],
        mode='markers',
        customdata=df.loc[:, ['Type']],
        hovertemplate="<b>%{text}</b><br><br>" +"Type: %{customdata[0]}<br>" +""+ "<extra 
 </extra>",
        showlegend=False,
        marker=go.scattermapbox.Marker(
                size=20,
                color=df['Code']
                ),
        text=df ['Name'],
        name = type
        ))

    return {'data': traces,
             'layout': go.Layout(hovermode='closest',
              height= 900,
              mapbox=dict(
                  accesstoken='MAPBOX_ACCESS_TOKEN',
                  bearing=0,
             center=go.layout.mapbox.Center(
                        lat=56.0,
                        lon=-4.0
                ),
            pitch=0,
            zoom=5
        ))}


app.layout = html.Div([
    dbc.Card(
        dbc.CardBody([
            dbc.Row([
                dbc.Col([
                    html.H1(['Project 1'],style={'text-align':'center'})
                ], width=15),
            ], align='center'),
            html.Br(),
            dbc.Row([
                dbc.Col([
                    html.Label(['Select Region'],style={'font-weight':'bold'},),
                     dcc.Dropdown(id='region-dropdown',
                                  options=[{'label':i,'value':i} for i in df['Region'].unique()],
                                  multi= True

                     )
                ], width=3),
                dbc.Col([
                   html.Div(
                            [
                            dbc.Button('Submit', id='submit-button', color='primary', className='mr-1')
                            ],style={'margin-top':'20px'}
                    )
                ], width=3),
            ], align='center'), 
            html.Br(),
            dbc.Row([
                dbc.Col([
                     html.Div([
                  dcc.Graph(id = 'graph',figure=update_map(df))
                  ])
                ], width=7),
                dbc.Col([
                    html.Div([
                  dcc.Graph(id = 'graph-1',figure=update_bar(df))
                  ])
                ], width=5),
            ], align='center'), 
            html.Br(),
            dbc.Row([
                dbc.Col([dash_table.DataTable(id='table',columns=[{'name': col, 'id': col} for col in df.columns],
                                               style_cell_conditional=[{'if': {'column_id': 'Code',} ,  'display': 'None',}],
        style_table={'overflowX': 'scroll'},
        style_cell={
            'minWidth': '100px', 'width': '100px', 'maxWidth': '90px',
            'height': 'auto',
            'overflow': 'hidden',
            'textOverflow': 'ellipsis','textAlign': 'left',
            'fontSize':20, 'font-family':'sans-serif'
        })
                ], width=8),
              
            ], align='center'),      
        ])
    ) 
])



@app.callback([Output('graph','figure'),
              Output('graph-1','figure')],
              [Input('submit-button','n_clicks')],
              [State('region-dropdown','value')],
             )

def update_graph(n_clicks,region): 
    frames = []
    for region_name in region:
            frames.append(df[(df['Region']==region_name)])
    df_filtered = pd.concat(frames,ignore_index=True)
    return [update_map(df_filtered), update_bar(df_filtered)]


@app.callback(
    Output('table', 'data'),
    Input('graph', 'clickData'),
    State('table', 'data'),
            )   

def update_table(selected_point, current_data):
    if selected_point is None:
        return current_data
    else:
        lat, lon = selected_point['points'][0]['lat'], selected_point['points'][0]['lon']
        selected_row = df[(df['Latitude'] == lat) & (df['Longitude'] == lon)]
        if selected_row.empty:
            return current_data
        else:
            return selected_row.to_dict('records')

if __name__ == '__main__':
    app.run_server()
python pandas plotly-dash
1个回答
0
投票

我设法通过在更新数据表的回调中添加一些元素并在数据表更新函数中添加另一个 if 语句来找到解决方案。 我还添加了一个清除数据按钮,用于清除所选数据

@app.callback(
Output('table', 'data'),
Output('graph', 'selectedData'),  # Clear selected data from map
Input('graph', 'clickData'),
Input('graph', 'selectedData'),
Input('clear-data-button', 'n_clicks'),
State('table', 'data'),
 )
def update_table(click_data, selected_data, clear_data_clicks, current_data):
ctx = dash.callback_context

# Determine the triggered input
triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]

if triggered_id == 'clear-data-button':
    # Clear the table data and the selected data from the map
    return [], None

selected_rows = set()

if selected_data:
    if 'points' in selected_data:
        selected_points = selected_data['points']
        for point in selected_points:
            lat, lon = point['lat'], point['lon']
            selected_row = df[(df['Latitude'] == lat) & (df['Longitude'] == lon)]
            if not selected_row.empty:
                selected_rows.add(selected_row.index[0])

if click_data:
    lat, lon = click_data['points'][0]['lat'], click_data['points'][0]['lon']
    selected_row = df[(df['Latitude'] == lat) & (df['Longitude'] == lon)]
    if not selected_row.empty:
        selected_rows.add(selected_row.index[0])

if not selected_rows:
    return current_data, None  # Keep the current selectedData

selected_data = df.iloc[list(selected_rows)]
return selected_data.to_dict('records'), None  # Clear selectedData
© www.soinside.com 2019 - 2024. All rights reserved.