Hot*_*one 6 python python-3.x pandas plotly-dash plotly-dash-datatable
与 qtTree 类似,我想深入了解数据表的列。我想用一个例子可以更好地说明这一点。假设我们有一个包含三列的数据框:国家/地区、城市、人口,例如:
Country City Population
USA New-York 19MM
China Shanghai 26MM
China Beijing 20MM
USA Los Angeles 12MM
France Paris 11MM
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以在虚线图数据表中理想地呈现这些数据,如下所示:
Country City Population
+USA 31MM
/----> New-York 19MM
/----> Los Angeles 12MM
+China 46MM
/----> Shanghai 26MM
/----> Beijing 20MM
+France 11MM
/----> Paris 11MM
Run Code Online (Sandbox Code Playgroud)
分组国家/城市将展开(或者可能在单击行 -?- 时隐藏/显示)。在国家一级,人口将是其选民的总和,在城市一级,人口将是来自该城市的人口。
库 dash_treeview_antd 允许树视图表示,但我不知道如何包含人口列。也许有一种更简单的方法,首先在 pandas 中进行 groupby,然后进行回调来隐藏/显示当前行选择/单击?
我一直在玩弄.groupbypandas 和回调中的' active_cell' Dash DataTable 属性。
def defineDF():
df = pd.DataFrame({'Country': ['USA', 'China', 'China', 'USA', 'France'],
'City': ['New-York', 'Shanghai', 'Beijing', 'Los Angeles', 'Paris'],
'Population': [19, 26, 20, 12, 11],
'Other': [5, 3, 4, 11, 43]})
df.sort_values(by=['Country', 'City'], inplace=True)
return df
def baseDF():
df = pd.DataFrame({'Country': ['USA', 'China', 'China', 'USA', 'France'],
'City': ['New-York', 'Shanghai', 'Beijing', 'Los Angeles', 'Paris'],
'Population': [19, 26, 20, 12, 11],
'Other': [5, 3, 4, 11, 43]})
df.sort_values(by=['Country', 'City'], inplace=True)
f = {'Population': 'sum', 'Other': 'sum'}
cols = ['Country']
return df.groupby(cols).agg(f).reset_index()
startDF = baseDF()
app.layout = html.Div([
html.Div(html.H6("Country/City population"), style={"text-align":"center"}),
html.Hr(),
dash_table.DataTable(
id='table',
columns=[{'name': i, 'id': i} for i in startDF.columns],
data = startDF.to_dict('records'),
selected_rows=[],
filter_action='native',
)
])
@app.callback([
Output('table', 'data'),
Output('table', 'columns')
],
[
Input('table', 'active_cell')
],
[
State('table', 'data'),
State('table', 'columns')
],
)
def updateGrouping(active_cell, power_position, power_position_cols):
if active_cell is None:
returndf = baseDF()
elif active_cell['column'] == 0:
returndf = defineDF()
else:
returndf = baseDF()
cols = [{'name': i, 'id': i} for i in returndf.columns]
return [returndf.to_dict('records'), cols]
Run Code Online (Sandbox Code Playgroud)
我快到了。一开始我只显示国家/地区列;最好也有 City 列,但值为空。然后,一旦用户单击一个国家/地区,则仅显示该国家/地区的城市(以及相应的人口/其他列,而表的其余部分保持不变)。我还没有在回调中使用current_dfNor ,但我怀疑它们可能会变得很方便。current_df_cols也许我可以根据活动单元格过滤国家/地区列?
data_table,具有基于行的下拉菜单,可触发回调这有点棘手,但希望以下示例可以帮助实现您正在尝试的目标。主要缺点可能是需要对参数进行硬编码dropdown_conditional(尽管,您可能不希望有更多列供用户交互,否则会禁止硬编码!)。因此,我认为这应该为您提供足以让您根据需要进一步自定义它的一般功能要点。
import pandas as pd
from collections import OrderedDict
from dash import Dash, Input, Output, State, dcc, html, callback
from dash.exceptions import PreventUpdate
from dash import dash_table
start_df = pd.DataFrame(
OrderedDict([("Country", ["USA", "China", "France"])])
)
start_df["City"] = ""
start_df["Population"] = [31, 46, 11]
population_df = pd.DataFrame(
OrderedDict(
[
("Country", ["USA", "China", "China", "USA", "France"]),
(
"City",
["New-York", "Shanghai", "Beijing", "Los Angeles", "Paris",],
),
("Population", [19, 26, 20, 12, 11]),
]
)
)
app = Dash(__name__)
app.layout = html.Div(
[
html.Div(
html.H1("Country/City population"), style={"text-align": "center"}
),
html.Hr(),
dash_table.DataTable(
id="table",
columns=[
{"id": "Country", "name": "Country",},
{"id": "City", "name": "City", "presentation": "dropdown",},
{"id": "Population", "name": "Population (Total [M])"},
],
data=start_df.to_dict("records"),
editable=True,
dropdown_conditional=[
{
"if": {
"column_id": "City", # skip-id-check
"filter_query": '{Country} eq "China"',
},
"options": [
{"label": i, "value": i}
for i in population_df[
population_df.Country == "China"
].City.values
],
},
{
"if": {
"column_id": "City", # skip-id-check
"filter_query": '{Country} eq "USA"',
},
"options": [
{"label": i, "value": i}
for i in population_df[
population_df.Country == "USA"
].City.values
],
},
{
"if": {
"column_id": "City", # skip-id-check
"filter_query": '{Country} eq "France"',
},
"options": [
{"label": i, "value": i}
for i in population_df[
population_df.Country == "France"
].City.values
],
},
],
style_cell={
"fontSize": "0.8rem",
"whiteSpace": "normal",
"padding": "3px",
"textOverflow": "ellipsis",
"textAlign": "center",
"maxWidth": "300px",
},
style_header={
"fontWeight": "500",
"fontSize": "0.8rem",
"cursor": "pointer",
},
),
html.Div(id="table_container"),
]
)
@callback(
Output("table", "data"),
Input("table", "data_timestamp"),
State("table", "data"),
)
def update_table(timestamp, rows):
print(timestamp)
for row in rows:
country = row["Country"]
city = row["City"]
if city == "" or city is None:
print(country)
population = start_df.set_index("Country").loc[country][
"Population"
]
print(population)
row["Population"] = population
elif city in population_df[["City"]].values:
print(city)
population = population_df.set_index("City").loc[city][
"Population"
]
print(population)
row["Population"] = population
return rows
if __name__ == "__main__":
print(start_df)
app.run(debug=True)
Run Code Online (Sandbox Code Playgroud)
print()使用/包含这些函数是为了调试目的。例如,在运行应用程序时将其提供给终端中的标准输出:
Dash is running on http://127.0.0.1:8050/
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
Country City Population
0 USA 31
1 China 46
2 France 11
None
USA
31
China
46
France
11
1690628030839
New-York
19
China
46
France
11
1690628033725
Los Angeles
12
China
46
France
11
1690628035972
USA
31
China
46
France
11
1690628038742
USA
31
Shanghai
26
France
11
1690628041373
USA
31
Shanghai
26
Paris
11
1690628043825
Los Angeles
12
Shanghai
26
Paris
11
1690628046159
Los Angeles
12
China
46
Paris
11
1690628047975
Los Angeles
12
China
46
France
11
1690628050125
USA
31
China
46
France
11
Run Code Online (Sandbox Code Playgroud)
您可以在其中看到与浏览器中应用程序中的数据表的每次交互都会首先触发为该交互记录的时间戳的打印,然后data_table由“城市”列中的下拉组件触发呈现的更改。
| 归档时间: |
|
| 查看次数: |
2673 次 |
| 最近记录: |