我下面有一个破折号应用程序。 目前,只要用户单击地图上的点,该应用程序就会更新破折号数据表。我对如何使用破折号地图工具(框选择和套索选择)来更新表格(也保留单击功能)有一点了解。 我尝试添加一个新的回调,其中包括破折号工具的“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()
我设法通过在更新数据表的回调中添加一些元素并在数据表更新函数中添加另一个 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