确保Dash App中Div组件的顺序

时间:2019-02-01 22:32:29

标签: python plotly-dash

当我创建一个包含边栏的仪表板应用程序时,用户可以在其中选择要绘制的数据的一部分(并在另一个选项卡中列出),我遇到了一个问题,即不同的dcc组件没有保持我指定的顺序。

更新

我创建了一个简化的可复制示例。我没有使用html和CSS的经验,所以我想问你如何确保html.Divhtml.P很好地遵循以下代码中指定的顺序:

所以:性别 - 注册日期 - 生日国家

import pandas as pd
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table
from datetime import datetime as dt

df = pd.DataFrame.from_dict({'Customer': [111, 222, 555, 666],
        'zip_city': ['Aguadilla', 'Aguadilla', 'Arecibo', 'Wrangell'],
        'zip_state': ['PR', 'TX', 'CA', 'MI'],
        'zip_latitude':[18.498987, 18.498987, 18.449732,56.409507],
        'zip_longitude':[-67.13699,-67.13699,-66.69879,-132.33822],
        'Birtdate': pd.to_datetime(['1964-04-28','1994-04-18','1993-04-04','1997-05-03'], format="%Y-%m-%d", utc=True, dayfirst=True),
        'JoinDate': pd.to_datetime(['1980-08-02','2008-03-24','2004-12-17','2010-12-11'], format="%Y-%m-%d", utc=True, dayfirst=True),
        'Gender':['m','f','m','alien']})



df["CustomerCount"] = df.groupby(["zip_city"], as_index=False)["Customer"].transform("count")

gender_options = []
for gender in df['Gender'].unique():
    gender_options.append({'label':str(gender),
                           'value':gender})

state_options = []
for state in df['zip_state'].unique():
    gender_options.append({'label':str(state),
                           'value':state})

app = dash.Dash()


app.css.append_css({'external_url': 'https://codepen.io/chriddyp/pen/bWLwgP.css'})

app.layout = html.Div([html.H1('A Dashboard', style={'textAlign':'center'}),
                       html.Div(children=[
                            html.H1('Input', style={'textAlign':'center'}),
                            html.H6('Gender'),
                            html.P(
                                    dcc.Checklist(id='gender-picker',
                                    options=gender_options,
                                    values=['m','f']
                                    )
                                ),
                            html.H6('Join Date'),
                            html.P(
                                    dcc.DatePickerRange(
                                            id='joindate',
                                            min_date_allowed=min(df.JoinDate),
                                            max_date_allowed=max(df.JoinDate),
                                            initial_visible_month=dt(1989, 11, 9),
                                            start_date=min(df.JoinDate),
                                            end_date=max(df.JoinDate)
                                            )
                                    ),
                            html.H6('Birthdate'),
                            html.P(
                                    dcc.DatePickerRange(
                                            id='birthdate',
                                            min_date_allowed=min(df['Birtdate']),
                                            max_date_allowed=max(df['Birtdate']),
                                            initial_visible_month=dt(1989, 11, 9),
                                            start_date=min(df['Birtdate']),
                                            end_date=max(df['Birtdate'])
                                            )
                                    ),
                            html.H6('State'),
                            html.P(html.Div([
                            dcc.Checklist(id='state-picker',
                                          options=state_options,
                                          values= df['zip_state'].unique().tolist()
                                          )
                                        ])
                                        )
                                ],
                               style = {'float':'left'},
                                className = "two columns"
                            ),
                        html.Div([dcc.Tabs(children=[dcc.Tab(label='Map',
                                                            children=html.Div([
                                                                    dcc.Graph(id='CustomerMap')
                                                                    ])
                                                            ),
                                                    dcc.Tab(label='Data',
                                                            children=[html.Div([dash_table.DataTable(
                                                                                id='table',
                                                                                columns = [{"name": i, "id": i} for i in df.columns],
                                                                                data = df.to_dict("rows")
                                                                                )])
                                                                    ]
                                                            )
                                                    ]
                                            )
                                ])
                        ]
                    )

@app.callback(
    dash.dependencies.Output('CustomerMap', 'figure'),
    [dash.dependencies.Input('gender-picker', 'values')])

def update_figure(selected_gender):    
    filtered_df = df[df['Gender'].isin(selected_gender)]
    filtered_df["CustomerCount"] = filtered_df.groupby(["zip_city"], as_index=False)["Customer"].transform("count")

    customerCount = filtered_df['CustomerCount'].tolist()
    zipcity = filtered_df['zip_city'].tolist()
    hovertext = []
    for i in range(len(customerCount)):
        k = str(zipcity[i]) + ':' + str(customerCount[i])
        hovertext.append(k)
    return {'data':[dict(
                        type = 'scattergeo',
                        locationmode = 'USA-states',
                        lon = filtered_df['zip_longitude'],
                        lat = filtered_df['zip_latitude'],
                        text = hovertext,
                        hoverinfo = 'text',
                        marker = dict(
                        size = filtered_df['CustomerCount'],
                        line = dict(width=0.5, color='rgb(40,40,40)'),
                        sizemode = 'area'
                        ),
                        transforms = [dict(
                        type = 'aggregate',
                        groups = filtered_df['zip_city'],
                        aggregations = [dict(target = filtered_df['Customer'], func = 'count', enabled = True)]
                                        )
                                        ]
                        )
                    ]
            }


@app.callback(
    dash.dependencies.Output('table', 'data'),
    [dash.dependencies.Input('gender-picker', 'values')])

def update_table(selected_gender):    
    filtered_df = df[df['Gender'].isin(selected_gender)]
    filtered_df["CustomerCount"] = filtered_df.groupby(["zip_city"], as_index=False)["Customer"].transform("count")
    return filtered_df.to_dict("rows")

if __name__ == '__main__':
    app.run_server()

但是在应用程序中,它会堆叠两个复选框的选项: Screenshot of the problem

2 个答案:

答案 0 :(得分:0)

我运行了您的代码,我认为它可以工作,这不是您想要的吗? enter image description here

答案 1 :(得分:0)

我发现了问题,这是一个复制粘贴错误:

gender_options = []
for gender in df['Gender'].unique():
    gender_options.append({'label':str(gender),
                           'value':gender})

state_options = []
for state in df['zip_state'].unique():
    gender_options.append({'label':str(state),
                           'value':state})

很显然,第二个循环会将状态添加到性别中,这意味着我可以准确地获得所请求的输出,但不是我想要的输出!将第二部分更改为:

state_options = []
for state in df['zip_state'].unique():
    state_options.append({'label':str(state),
                           'value':state})

解决了问题。