添加下一个/上一个按钮以绘制破折号

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

dash 应用程序主要有两个图,第一个图用于显示第二个图的数据。这是通过在第一个数据点中选择一个数据点,它将加载一个连接的数据帧以在第二个数据帧中显示。

现在,我想在第一个图中添加下一个/上一个按钮,以便通过按钮简单地在数据点之间切换,而不是仅使用鼠标。但我已经很努力了很长一段时间了,但还是没能做到。说实话,我的头因我尝试过的所有事情而旋转,现在我很困惑,我不知道如何继续或尝试其他什么。这就是为什么我感谢任何能够继续前进的帮助。

我有这个数据框:

df2.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100080 entries, 0 to 100079
Data columns (total 7 columns):
 #   Column    Non-Null Count   Dtype         
---  ------    --------------   -----         
 0   Device    100080 non-null  category      
 1   time      100080 non-null  datetime64[ns]
 2   time2     100080 non-null  float64       
 3   Path      100080 non-null  category      
 4   variable  100080 non-null  object        
 5   value     100080 non-null  float64       
 6   path      100080 non-null  category      
dtypes: category(3), datetime64[ns](1), float64(2), object(1)
memory usage: 3.3+ MB

有了这些数据:

    Device  time    time2   Path    variable    value   path
0   A 2022-09-27 11:57:26.801999    0.0 C:\Users\2022_09_27_11_57_26_,80.csv    V+  7.985262    C:\Users\2022_09_27_11_57_26_,80.csv
1   A 2022-09-27 11:57:26.802199    0.0002  C:\Users\2022_09_27_11_57_26_,80.csv    V+  7.981362    C:\Users\2022_09_27_11_57_26_,80.csv
2   A 2022-09-27 11:57:26.802399    0.0004  C:\Users\2022_09_27_11_57_26_,80.csv    V+  7.981687    C:\Users\2022_09_27_11_57_26_,80.csv
3   A 2022-09-27 11:57:26.802599    0.0006000000000000001   C:\Users\2022_09_27_11_57_26_,80.csv    V+  7.983637    C:\Users\2022_09_27_11_57_26_,80.csv
4   A 2022-09-27 11:57:26.802799    0.0008  C:\Users\2022_09_27_11_57_26_,80.csv    V+  7.983637    C:\Users\2022_09_27_11_57_26_,80.csv
5   A 2022-09-27 11:57:26.802999    0.001   C:\Users\2022_09_27_11_57_26_,80.csv    V+  7.984612    C:\Users\2022_09_27_11_57_26_,80.csv
6   A 2022-09-27 11:57:26.803199    0.0012000000000000001   C:\Users\2022_09_27_11_57_26_,80.csv    V+  7.983637    C:\Users\2022_09_27_11_57_26_,80.csv
7   A 2022-09-27 11:57:26.803399    0.0014  C:\Users\2022_09_27_11_57_26_,80.csv    V+  7.982012    C:\Users\2022_09_27_11_57_26_,80.csv
...

这是我的布局:

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, title='Dashboard', external_stylesheets=external_stylesheets, assets_folder = 'assets')          
colors = {
        'background': '#000000',
        'text': '#f3ff00'
        }

# Define the app
app.layout = html.Div(
                    children = [
    
                            html.Div([
                                    html.H4('Dauertest'),
                                    html.Div(children = ""),

                                    # Draw graph
                                    dcc.Graph(id = 'General' 
                                              , figure={}
                                              ),

                                    dcc.RadioItems(
                                                  id="signals",
                                                  options = ['V+', 'V-', 'I_A', 'I_fil'],
                                                  value = 'V+',
                                                  inline=True
                                                  ),
                                    html.Br(),
                                    dcc.Graph(id = 'Zoomed' 
                                              #, figure={}
                                              #, hoverData = {'points': [{'customdata': df2['path'][0]}]}
                                              ),
                                    html.Br(),
                                    ]),
                                    
                                    html.Br(),
                                    html.Br(),
                                    html.Br(),
                                    
                            # New row
                            html.Div([
                                html.Div([           
                                    dcc.Dropdown(
                                                  id="select",
                                                  options = list(all_df['Device'].unique()),
                                                  value = list(all_df['Device'].unique()[0])
                                                  ),                                    
                                    dcc.Graph(id = 'shared' 
                                              , figure={}
                                              ),
                                        #], className='six columns'),
                                        ], className='twelve columns'),
                                    ], className='row')
])

以及这些图:

#%% Plot 1

    @app.callback(
                  Output("General", "figure"), 
                  Input("signals", "value")
                  )
    def update_scatter_chart(signals):
        df3 = df2.query('variable==@signals').groupby('path').first() 
    
        
        fig_general = px.scatter(df3
                                  , x = "time"
                                  , y = 'value'
                                  , custom_data = ['Path']
                                  , color = 'Device'
                                  , symbol = 'variable'
                                  , hover_name = "Path"
                                  , opacity = 0.75
                                  , template = 'plotly_dark'
                                  , marginal_y = "rug"
                                  , title = "All devices <br><sup> Only the first data point of below selected variable plus of each error file</sup>"
                                  , labels=dict(x = "absolute time")
                                  )
        fig_general.update_layout(
                                  clickmode = 'event+select'
                                  , xaxis = {'domain': [0.0, 0.85]}
                                  , xaxis2 = {'domain': [0.86, 0.97]}
                                  #, xaxis3 = {'domain': [0.85, 1.0]}
                                  , transition_duration = 500
                                  , autosize = True
                                  , height = 700
                                  , hovermode = 'closest'
                                  )
        fig_general.update_traces(marker = dict(size = 16,
                                                  line=dict(width = 2,
                                                            color = 'rgba(255, 255, 255, 0.3)'),
                                                  opacity = 0.75
                                                  )
                                    , selected_marker = dict(size = 20 
                                                             , opacity = 0.95
                                                             , color='rgba( 240, 240, 240, 0.95)')
                                    , unselected = dict(marker = dict(opacity = 0.75)
                                                       ) 
                                    , hovertemplate="<br>".join([
                                                               "time: %{x}",
                                                               "value: %{y}",
                                                              ])
                                      )
             
        return fig_general
    
    
#%% Plot 2
    def update_zoom_chart(df5, device_name):
            
    
        fig_zoom = px.scatter(df5
                                  , x = "time2"
                                  , y = 'value'
                                  , color = 'variable'
                                  , symbol = 'variable'
                                  #, hover_name = "Device"
                                  , opacity = 0.7
                                  , template = 'plotly_dark'
                                  , title = device_name
                                  , color_discrete_map = {"I_A": 'orangered', "I_fil" : 'lawngreen', "V+" : "dodgerblue", "V-" : "chocolate"}
                                  , labels = dict(x = "t / ms", y = "value")
                                  )
        fig_zoom.update_xaxes( nticks = 10 )
        fig_zoom.update_traces(marker = dict(
                                                size = 5
                                                )
                               )
        fig_zoom.update_layout(
                               transition_duration = 500
                               , autosize = True
                               , height = 600
                               , hovermode='x unified'
                               , hoverlabel=dict(
                                                 bgcolor="rgba(0, 0, 0, 0.4)", 
                                                 font_size=14, 
                                                 font_family="Rockwell"
                                                 )
                              )
        return fig_zoom
plotly plotly-dash plotly-python
1个回答
0
投票

在此示例中,左侧有一个散点图。当您记录任何数据点时,它会选择下拉菜单中突出显示的项目。当该下拉菜单更新时,右侧的两个折线图也会更新。因此,您可以通过单击散点图中的数据点来选择项目,也可以在显示列表中所有数据点的下拉菜单中逐项选择。我还添加了“上一个”和“下一个”按钮,您可以单击该按钮循环浏览下拉菜单中的项目。

from dash import Dash, html, dcc, Input, State, Output, callback, ctx
import pandas as pd
import plotly.express as px

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = Dash(__name__, external_stylesheets=external_stylesheets)

df = pd.read_csv('https://plotly.github.io/datasets/country_indicators.csv')
country_list = df['Country Name'].unique().tolist()

app.layout = html.Div([
    html.Div([

        html.Div([
            dcc.Dropdown(
                df['Indicator Name'].unique(),
                'Fertility rate, total (births per woman)',
                id='crossfilter-xaxis-column',
            ),
            dcc.RadioItems(
                ['Linear', 'Log'],
                'Linear',
                id='crossfilter-xaxis-type',
                labelStyle={'display': 'inline-block', 'marginTop': '5px'}
            )
        ],
        style={'width': '49%', 'display': 'inline-block'}),

        html.Div([
            dcc.Dropdown(
                df['Indicator Name'].unique(),
                'Life expectancy at birth, total (years)',
                id='crossfilter-yaxis-column'
            ),
            dcc.RadioItems(
                ['Linear', 'Log'],
                'Linear',
                id='crossfilter-yaxis-type',
                labelStyle={'display': 'inline-block', 'marginTop': '5px'}
            )
        ], style={'width': '49%', 'float': 'right', 'display': 'inline-block'})
    ], style={
        'padding': '10px 5px'
    }),

    html.Div([
        dcc.Graph(
            id='crossfilter-indicator-scatter',
            hoverData={'points': [{'customdata': 'Japan'}]}
        )
    ], style={'width': '49%', 'display': 'inline-block', 'padding': '0 20'}),
    html.Div([
        dcc.Graph(id='x-time-series'),
        dcc.Graph(id='y-time-series'),
    ], style={'display': 'inline-block', 'width': '49%'}),

    html.Div(dcc.Slider(
        df['Year'].min(),
        df['Year'].max(),
        step=None,
        id='crossfilter-year--slider',
        value=df['Year'].max(),
        marks={str(year): str(year) for year in df['Year'].unique()}
    ), style={'width': '49%', 'padding': '0px 20px 20px 20px'}),

    dcc.Dropdown(
        df['Country Name'].unique(),
        id='country',
    ),

    html.Button('Previous', id='btn-nclicks-1', n_clicks=0),
    html.Button('Next', id='btn-nclicks-2', n_clicks=0),


])


@callback(
    Output('crossfilter-indicator-scatter', 'figure'),
    Input('crossfilter-xaxis-column', 'value'),
    Input('crossfilter-yaxis-column', 'value'),
    Input('crossfilter-xaxis-type', 'value'),
    Input('crossfilter-yaxis-type', 'value'),
    Input('crossfilter-year--slider', 'value'))
def update_graph(xaxis_column_name, yaxis_column_name,
                 xaxis_type, yaxis_type,
                 year_value):
    dff = df[df['Year'] == year_value]

    fig = px.scatter(x=dff[dff['Indicator Name'] == xaxis_column_name]['Value'],
            y=dff[dff['Indicator Name'] == yaxis_column_name]['Value'],
            hover_name=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name']
            )

    fig.update_traces(customdata=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'])

    fig.update_xaxes(title=xaxis_column_name, type='linear' if xaxis_type == 'Linear' else 'log')

    fig.update_yaxes(title=yaxis_column_name, type='linear' if yaxis_type == 'Linear' else 'log')

    fig.update_layout(margin={'l': 40, 'b': 40, 't': 10, 'r': 0}, hovermode='closest')

    return fig


def create_time_series(dff, axis_type, title):

    fig = px.scatter(dff, x='Year', y='Value')

    fig.update_traces(mode='lines+markers')

    fig.update_xaxes(showgrid=False)

    fig.update_yaxes(type='linear' if axis_type == 'Linear' else 'log')

    fig.add_annotation(x=0, y=0.85, xanchor='left', yanchor='bottom',
                       xref='paper', yref='paper', showarrow=False, align='left',
                       text=title)

    fig.update_layout(height=225, margin={'l': 20, 'b': 30, 'r': 10, 't': 10})

    return fig


@callback(
    Output('x-time-series', 'figure'),
    Input('crossfilter-xaxis-column', 'value'),
    Input('crossfilter-xaxis-type', 'value'),
    Input('country', 'value'))
def update_x_timeseries(xaxis_column_name, axis_type, input_country):
    country_name = input_country
    dff = df[df['Country Name'] == country_name]
    dff = dff[dff['Indicator Name'] == xaxis_column_name]
    title = '<b>{}</b><br>{}'.format(country_name, xaxis_column_name)
    return create_time_series(dff, axis_type, title)


@callback(
    Output('y-time-series', 'figure'),
    Input('crossfilter-yaxis-column', 'value'),
    Input('crossfilter-yaxis-type', 'value'),
    Input('country', 'value'))
def update_y_timeseries(yaxis_column_name, axis_type, input_country):
    dff = df[df['Country Name'] == input_country]
    dff = dff[dff['Indicator Name'] == yaxis_column_name]
    return create_time_series(dff, axis_type, yaxis_column_name)


@callback(
    Output('country', 'value'),
    Input('crossfilter-indicator-scatter', 'clickData'),
    Input('crossfilter-yaxis-column', 'value'),
    Input('crossfilter-yaxis-type', 'value'),
    Input('btn-nclicks-1', 'n_clicks'),
    Input('btn-nclicks-2', 'n_clicks'),
    State('country', 'value'),
)
def update_y_timeseries(clickData, yaxis_column_name, axis_type, n_clicks_1, n_clicks_2, current_country):

    if ctx.triggered_id is None:
        return country_list[0]
    elif "btn-nclicks-1" == ctx.triggered_id:
        index = country_list.index(current_country)
        try:
            next_country = country_list[index - 1]
        except:
            next_country = country_list[0]
        return next_country
    elif "btn-nclicks-2" == ctx.triggered_id:
        index = country_list.index(current_country)
        try:
            next_country = country_list[index + 1]
        except:
            next_country = country_list[0]
        return next_country
    return clickData['points'][0]['customdata']


if __name__ == '__main__':
    app.run(debug=True)
© www.soinside.com 2019 - 2024. All rights reserved.