Plotly-Dash:如何过滤具有多个数据框列的仪表板?
Plotly-Dash: How to filter dashboard with multiple dataframe columns?
我有一个使用 dash
构建的 Python 仪表板,我想在 Investor
或 [=14] 上进行过滤=]列。
Investor Fund Period Date Symbol Shares Value
0 Rick Fund 3 2019-06-30 AVLR 3 9
1 Faye Fund 2 2015-03-31 MEG 11 80
2 Rick Fund 3 2018-12-31 BAC 10 200
3 Dre Fund 4 2020-06-30 PLOW 2 10
4 Faye Fund 2 2015-03-31 DNOW 10 100
5 Mike Fund 1 2015-03-31 JNJ 1 10
6 Mike Fund 1 2018-12-31 QSR 4 20
7 Mike Fund 1 2018-12-31 LBTYA 3 12
换句话说,用户应该能够在同一筛选字段中输入一个或多个投资者,and/or一个或多个基金,仪表板将相应更新。所以我想我需要改变:
options=[{'label': i, 'value': i} for i in df['Investor'].unique()]
类似 groupby
但我不是积极的?这是我的代码:
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
data = {'Investor': {0: 'Rick', 1: 'Faye', 2: 'Rick', 3: 'Dre', 4: 'Faye', 5: 'Mike', 6: 'Mike', 7: 'Mike'},
'Fund': {0: 'Fund 3', 1: 'Fund 2', 2: 'Fund 3', 3: 'Fund 4', 4: 'Fund 2', 5: 'Fund 1', 6: 'Fund 1', 7: 'Fund 1'},
'Period Date': {0: '2019-06-30', 1: '2015-03-31', 2: '2018-12-31', 3: '2020-06-30', 4: '2015-03-31', 5: '2015-03-31', 6: '2018-12-31', 7: '2018-12-31'},
'Symbol': {0: 'AVLR', 1: 'MEG', 2: 'BAC', 3: 'PLOW', 4: 'DNOW', 5: 'JNJ', 6: 'QSR', 7: 'LBTYA'},
'Shares': {0: 3, 1: 11, 2: 10, 3: 2, 4: 10, 5: 1, 6: 4, 7: 3},
'Value': {0: 9, 1: 80, 2: 200, 3: 10, 4: 100, 5: 10, 6: 20, 7: 12}}
df = pd.DataFrame.from_dict(data)
def generate_table(dataframe, max_rows=100):
return html.Table(
# Header
[html.Tr([html.Th(col) for col in dataframe.columns])] +
# Body
[html.Tr([
html.Td(dataframe.iloc[i][col]) for col in dataframe.columns
]) for i in range(min(len(dataframe), max_rows))]
)
app = dash.Dash()
app.layout = html.Div(
children=[html.H4(children='Investor Portfolio'),
dcc.Dropdown(
id='dropdown',
options=[{'label': i, 'value': i} for i in df['Investor'].unique()],
multi=True, placeholder='Filter by Investor or Fund...'),
html.Div(id='table-container')
])
@app.callback(dash.dependencies.Output('table-container', 'children'),
[dash.dependencies.Input('dropdown', 'value')])
def display_table(dropdown_value):
if dropdown_value is None:
return generate_table(df)
dff = df[df.Investor.str.contains('|'.join(dropdown_value))]
dff = dff[['Investor', 'Period Date', 'Symbol','Shares', 'Value']]
return generate_table(dff)
if __name__ == '__main__':
app.run_server(debug=True)
诚然,我是 Dash 的新手,但据我所知,您可以通过扩展选项列表然后在 dff
中使用 or
条件来实现您想要的您在 Dash 应用程序中显示以包含 Fund
列。
这有点蛮力,更好的解决方案是让 Dash 知道您选择的选项来自哪些列。但是,只有当来自不同列的条目包含相同的字符串时才会出现问题(此处 Investor
和 Fund
的唯一值永远不相同)。
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
data = {'Investor': {0: 'Rick', 1: 'Faye', 2: 'Rick', 3: 'Dre', 4: 'Faye', 5: 'Mike', 6: 'Mike', 7: 'Mike'},
'Fund': {0: 'Fund 3', 1: 'Fund 2', 2: 'Fund 3', 3: 'Fund 4', 4: 'Fund 2', 5: 'Fund 1', 6: 'Fund 1', 7: 'Fund 1'},
'Period Date': {0: '2019-06-30', 1: '2015-03-31', 2: '2018-12-31', 3: '2020-06-30', 4: '2015-03-31', 5: '2015-03-31', 6: '2018-12-31', 7: '2018-12-31'},
'Symbol': {0: 'AVLR', 1: 'MEG', 2: 'BAC', 3: 'PLOW', 4: 'DNOW', 5: 'JNJ', 6: 'QSR', 7: 'LBTYA'},
'Shares': {0: 3, 1: 11, 2: 10, 3: 2, 4: 10, 5: 1, 6: 4, 7: 3},
'Value': {0: 9, 1: 80, 2: 200, 3: 10, 4: 100, 5: 10, 6: 20, 7: 12}}
df = pd.DataFrame.from_dict(data)
def generate_table(dataframe, max_rows=100):
return html.Table(
# Header
[html.Tr([html.Th(col) for col in dataframe.columns])] +
# Body
[html.Tr([
html.Td(dataframe.iloc[i][col]) for col in dataframe.columns
]) for i in range(min(len(dataframe), max_rows))]
)
app = dash.Dash()
app.layout = html.Div(
children=[html.H4(children='Investor Portfolio'),
dcc.Dropdown(
id='dropdown',
## extend the options to consider unique Fund values as well
options=[{'label': i, 'value': i} for i in df['Investor'].unique()] + [{'label': i, 'value': i} for i in df['Fund'].unique()],
multi=True, placeholder='Filter by Investor or Fund...'),
html.Div(id='table-container')
])
@app.callback(dash.dependencies.Output('table-container', 'children'),
[dash.dependencies.Input('dropdown', 'value')])
def display_table(dropdown_value):
if dropdown_value is None:
return generate_table(df)
## add an 'or' condition for the other column you want to use to slice the df
## and update the columns that are displayed
dff = df[df.Investor.str.contains('|'.join(dropdown_value)) | df.Fund.str.contains('|'.join(dropdown_value))]
dff = dff[['Investor', 'Fund', 'Period Date', 'Symbol','Shares', 'Value']]
return generate_table(dff)
if __name__ == '__main__':
app.run_server(debug=True)
我有一个使用 dash
构建的 Python 仪表板,我想在 Investor
或 [=14] 上进行过滤=]列。
Investor Fund Period Date Symbol Shares Value
0 Rick Fund 3 2019-06-30 AVLR 3 9
1 Faye Fund 2 2015-03-31 MEG 11 80
2 Rick Fund 3 2018-12-31 BAC 10 200
3 Dre Fund 4 2020-06-30 PLOW 2 10
4 Faye Fund 2 2015-03-31 DNOW 10 100
5 Mike Fund 1 2015-03-31 JNJ 1 10
6 Mike Fund 1 2018-12-31 QSR 4 20
7 Mike Fund 1 2018-12-31 LBTYA 3 12
换句话说,用户应该能够在同一筛选字段中输入一个或多个投资者,and/or一个或多个基金,仪表板将相应更新。所以我想我需要改变:
options=[{'label': i, 'value': i} for i in df['Investor'].unique()]
类似 groupby
但我不是积极的?这是我的代码:
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
data = {'Investor': {0: 'Rick', 1: 'Faye', 2: 'Rick', 3: 'Dre', 4: 'Faye', 5: 'Mike', 6: 'Mike', 7: 'Mike'},
'Fund': {0: 'Fund 3', 1: 'Fund 2', 2: 'Fund 3', 3: 'Fund 4', 4: 'Fund 2', 5: 'Fund 1', 6: 'Fund 1', 7: 'Fund 1'},
'Period Date': {0: '2019-06-30', 1: '2015-03-31', 2: '2018-12-31', 3: '2020-06-30', 4: '2015-03-31', 5: '2015-03-31', 6: '2018-12-31', 7: '2018-12-31'},
'Symbol': {0: 'AVLR', 1: 'MEG', 2: 'BAC', 3: 'PLOW', 4: 'DNOW', 5: 'JNJ', 6: 'QSR', 7: 'LBTYA'},
'Shares': {0: 3, 1: 11, 2: 10, 3: 2, 4: 10, 5: 1, 6: 4, 7: 3},
'Value': {0: 9, 1: 80, 2: 200, 3: 10, 4: 100, 5: 10, 6: 20, 7: 12}}
df = pd.DataFrame.from_dict(data)
def generate_table(dataframe, max_rows=100):
return html.Table(
# Header
[html.Tr([html.Th(col) for col in dataframe.columns])] +
# Body
[html.Tr([
html.Td(dataframe.iloc[i][col]) for col in dataframe.columns
]) for i in range(min(len(dataframe), max_rows))]
)
app = dash.Dash()
app.layout = html.Div(
children=[html.H4(children='Investor Portfolio'),
dcc.Dropdown(
id='dropdown',
options=[{'label': i, 'value': i} for i in df['Investor'].unique()],
multi=True, placeholder='Filter by Investor or Fund...'),
html.Div(id='table-container')
])
@app.callback(dash.dependencies.Output('table-container', 'children'),
[dash.dependencies.Input('dropdown', 'value')])
def display_table(dropdown_value):
if dropdown_value is None:
return generate_table(df)
dff = df[df.Investor.str.contains('|'.join(dropdown_value))]
dff = dff[['Investor', 'Period Date', 'Symbol','Shares', 'Value']]
return generate_table(dff)
if __name__ == '__main__':
app.run_server(debug=True)
诚然,我是 Dash 的新手,但据我所知,您可以通过扩展选项列表然后在 dff
中使用 or
条件来实现您想要的您在 Dash 应用程序中显示以包含 Fund
列。
这有点蛮力,更好的解决方案是让 Dash 知道您选择的选项来自哪些列。但是,只有当来自不同列的条目包含相同的字符串时才会出现问题(此处 Investor
和 Fund
的唯一值永远不相同)。
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
data = {'Investor': {0: 'Rick', 1: 'Faye', 2: 'Rick', 3: 'Dre', 4: 'Faye', 5: 'Mike', 6: 'Mike', 7: 'Mike'},
'Fund': {0: 'Fund 3', 1: 'Fund 2', 2: 'Fund 3', 3: 'Fund 4', 4: 'Fund 2', 5: 'Fund 1', 6: 'Fund 1', 7: 'Fund 1'},
'Period Date': {0: '2019-06-30', 1: '2015-03-31', 2: '2018-12-31', 3: '2020-06-30', 4: '2015-03-31', 5: '2015-03-31', 6: '2018-12-31', 7: '2018-12-31'},
'Symbol': {0: 'AVLR', 1: 'MEG', 2: 'BAC', 3: 'PLOW', 4: 'DNOW', 5: 'JNJ', 6: 'QSR', 7: 'LBTYA'},
'Shares': {0: 3, 1: 11, 2: 10, 3: 2, 4: 10, 5: 1, 6: 4, 7: 3},
'Value': {0: 9, 1: 80, 2: 200, 3: 10, 4: 100, 5: 10, 6: 20, 7: 12}}
df = pd.DataFrame.from_dict(data)
def generate_table(dataframe, max_rows=100):
return html.Table(
# Header
[html.Tr([html.Th(col) for col in dataframe.columns])] +
# Body
[html.Tr([
html.Td(dataframe.iloc[i][col]) for col in dataframe.columns
]) for i in range(min(len(dataframe), max_rows))]
)
app = dash.Dash()
app.layout = html.Div(
children=[html.H4(children='Investor Portfolio'),
dcc.Dropdown(
id='dropdown',
## extend the options to consider unique Fund values as well
options=[{'label': i, 'value': i} for i in df['Investor'].unique()] + [{'label': i, 'value': i} for i in df['Fund'].unique()],
multi=True, placeholder='Filter by Investor or Fund...'),
html.Div(id='table-container')
])
@app.callback(dash.dependencies.Output('table-container', 'children'),
[dash.dependencies.Input('dropdown', 'value')])
def display_table(dropdown_value):
if dropdown_value is None:
return generate_table(df)
## add an 'or' condition for the other column you want to use to slice the df
## and update the columns that are displayed
dff = df[df.Investor.str.contains('|'.join(dropdown_value)) | df.Fund.str.contains('|'.join(dropdown_value))]
dff = dff[['Investor', 'Fund', 'Period Date', 'Symbol','Shares', 'Value']]
return generate_table(dff)
if __name__ == '__main__':
app.run_server(debug=True)