如何将 selectedData 输入的值添加到列表中?

How to add values from selectedData input to a list?

我构建了一个 Plotly Dash 网络应用程序来显示传感器数据。我想要一张可以 select 车站的地图,因此我可以看到时间序列图表。

这是我现在的回拨:

@app.callback(
    Output('time_series1', 'figure'),
    Input('map_sensors', 'selectedData'))

def display_selected_data(selectedData):
    if selectedData is None: # Plot whole Dataframe if nothing is selected.
        fig = px.line(data_frame=df, x='date.utc', y='value', color='location')
    
        return fig
    
    else:
        selectedData['points'][0]['customdata'][0] # This line shows me the name of the location and I want to add this to a list
        return 

我可以在 selected 数据中显示位置。现在我的问题是,如何将其添加到列表中?

我的目标是像这样过滤数据框 dff2 = df[df.location.isin(selected_locations)] 以便我只绘制 selected 位置。

我现在的完整应用程序:

from jupyter_dash import JupyterDash
import plotly.graph_objs as go
from dash import Dash, dcc, html, Input, Output, State
import pandas as pd
import plotly.express as px
import json

loc = pd.read_csv('location_sensors.csv')
df = pd.read_csv('measurement.csv')
style = {'width': '50%', 'height': '500px', 'float': 'left'}

# Build small example app.
app = dash.Dash(__name__)

styles = {
    'pre': {
        'border': 'thin lightgrey solid',
        'overflowX': 'scroll'
    }
}

fig_map = px.scatter_mapbox(loc, lat="lat", lon="lon", hover_name="location", 
                           hover_data={'location':True, 'lat':False, 'lon':False}, zoom=3, height=600,
                           color='location', mapbox_style="open-street-map")
fig_map.update_layout(clickmode='event+select')

app.layout =   html.Div([
        dcc.Graph(id='map_sensors', figure=fig_map , className='six columns'),
      
    html.Div([dcc.Graph(
                    id='time_series1',
                    style={'height': 400}
                ),
])
])

@app.callback(
    Output('time_series1', 'figure'),
    Input('map_sensors', 'selectedData'))

def display_selected_data(selectedData):
    if selectedData is None:
        fig = px.line(data_frame=df, x='date.utc', y='value', color='location')
    
        return fig
    
    else:
        # Here I want to filter the dataframe to the selected locations.
        return 
    
if __name__ == '__main__':
    app.run_server()

位置 csv 数据:

lat,lon,location
51.20966,4.43182,BETR801
48.83722,2.3939,FR04014
51.49467,-0.13193,London Westminster

时序数据: https://github.com/pandas-dev/pandas/blob/master/doc/data/air_quality_long.csv

对于您的 @app.callback 装饰器,我想您希望您的输入是 clickData 而不是 selectionData。如果你看文档here中的第一个例子,一旦你在地图上点击了一个位置,它是灰色的,当你稍后再次点击它时,clickData会输入一个带有标记信息的字典,而selectionData 将输入 null(这意味着如果您使用 selectionData 而不是 clickData,dash 将无法知道您何时再次单击该点变灰)

然后您可以拥有一个根据用户选择和取消选择的位置而变化的动态列表。也是一个非常小的问题,但我将您的 DataFrame 变量名称从 loc 更改为 locs 因为 .loc 是一个 pandas DataFrame 方法。

from jupyter_dash import JupyterDash
import plotly.graph_objs as go
import dash
from dash import Dash, dcc, html, Input, Output, State
import pandas as pd
import plotly.express as px
import json

locs = pd.read_csv('location_sensors.csv')
df = pd.read_csv('https://raw.githubusercontent.com/pandas-dev/pandas/master/doc/data/air_quality_long.csv')

style = {'width': '50%', 'height': '500px', 'float': 'left'}

# Build small example app.
app = dash.Dash(__name__)

styles = {
    'pre': {
        'border': 'thin lightgrey solid',
        'overflowX': 'scroll'
    }
}

fig_map = px.scatter_mapbox(locs, lat="lat", lon="lon", hover_name="location", 
                           hover_data={'location':True, 'lat':False, 'lon':False}, zoom=3, height=600,
                           color='location', mapbox_style="open-street-map")

fig_map.update_layout(clickmode='event+select')

app.layout = html.Div([
    dcc.Graph(id='map_sensors', figure=fig_map , className='six columns'),
    html.Div([dcc.Graph(
        id='time_series1',
        style={'height': 400}
        ),
    ])
])

## define a list that will hold the columns of the dataframe
## this will be used to modify the px.line chart
selected_locations = list(locs['location'])

@app.callback(
    Output('time_series1', 'figure'),
    Input('map_sensors', 'clickData'))
def display_selected_data(clickData):
    ## when the app initializes
    if clickData is None:
        fig = px.line(data_frame=df, x='date.utc', y='value', color='location')

    ## when the user clicks on one of the loc points
    else:
        selection = clickData['points'][0]['customdata'][0]
        if selection in selected_locations:
            selected_locations.remove(selection)
        else:
            selected_locations.append(selection)
        fig = px.line(data_frame=df[df.location.isin(selected_locations)], x='date.utc', y='value', color='location')
    return fig
    
if __name__ == '__main__':
    app.run_server(debug=True)