Spaces:
Sleeping
Sleeping
Commit
·
a5a4e08
1
Parent(s):
b6e726c
commit
Browse files
app.py
CHANGED
|
@@ -43,28 +43,43 @@ def get_topics():
|
|
| 43 |
return sorted(df['topic'].dropna().unique().tolist())
|
| 44 |
return []
|
| 45 |
|
| 46 |
-
def get_specific_categories():
|
| 47 |
-
"""Get unique specific categories
|
| 48 |
if df.empty:
|
| 49 |
return []
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
return []
|
| 53 |
|
| 54 |
-
def get_locations():
|
| 55 |
-
"""Get unique locations
|
| 56 |
if df.empty:
|
| 57 |
return []
|
| 58 |
-
|
| 59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
return []
|
| 61 |
|
| 62 |
-
def get_impacts():
|
| 63 |
-
"""Get unique impact types
|
| 64 |
if df.empty:
|
| 65 |
return []
|
| 66 |
-
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
return []
|
| 69 |
|
| 70 |
def get_regions():
|
|
@@ -264,27 +279,6 @@ def create_box_plot(filtered_df):
|
|
| 264 |
fig.update_layout(xaxis_tickangle=-45, height=600)
|
| 265 |
return fig
|
| 266 |
|
| 267 |
-
def get_summary_stats(filtered_df):
|
| 268 |
-
"""Generate summary statistics for filtered data"""
|
| 269 |
-
if filtered_df.empty:
|
| 270 |
-
return "No data available for the selected filters"
|
| 271 |
-
|
| 272 |
-
stats = filtered_df['value'].describe()
|
| 273 |
-
|
| 274 |
-
summary = f"""
|
| 275 |
-
### Summary Statistics
|
| 276 |
-
|
| 277 |
-
- **Count**: {stats['count']:.0f} data points
|
| 278 |
-
- **Mean**: ${stats['mean']:,.2f}
|
| 279 |
-
- **Median**: ${stats['50%']:,.2f}
|
| 280 |
-
- **Std Dev**: ${stats['std']:,.2f}
|
| 281 |
-
- **Min**: ${stats['min']:,.2f}
|
| 282 |
-
- **Max**: ${stats['max']:,.2f}
|
| 283 |
-
- **25th Percentile**: ${stats['25%']:,.2f}
|
| 284 |
-
- **75th Percentile**: ${stats['75%']:,.2f}
|
| 285 |
-
"""
|
| 286 |
-
|
| 287 |
-
return summary
|
| 288 |
|
| 289 |
def get_data_table(filtered_df, max_rows=1000):
|
| 290 |
"""Return filtered data as a dataframe with formatted values"""
|
|
@@ -400,11 +394,6 @@ with gr.Blocks(title="GVFD Navigator", theme=gr.themes.Soft()) as demo:
|
|
| 400 |
column_widths=["10%", "12%", "12%", "12%", "12%", "10%", "12%", "10%", "10%"]
|
| 401 |
)
|
| 402 |
|
| 403 |
-
with gr.Row():
|
| 404 |
-
with gr.Column():
|
| 405 |
-
gr.Markdown("### Summary Statistics")
|
| 406 |
-
stats_output = gr.Markdown(value=get_summary_stats(df))
|
| 407 |
-
|
| 408 |
# Visualizations below the table
|
| 409 |
gr.Markdown("## Visualizations")
|
| 410 |
gr.Markdown("The charts and maps below reflect your filtered data selection from above.")
|
|
@@ -560,6 +549,14 @@ with gr.Blocks(title="GVFD Navigator", theme=gr.themes.Soft()) as demo:
|
|
| 560 |
""")
|
| 561 |
|
| 562 |
# Event handlers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 563 |
def update_all(search, countries, topics, categories, locations, impacts, regions, min_val, max_val):
|
| 564 |
"""Update all views when filters are applied"""
|
| 565 |
# First filter the data
|
|
@@ -578,13 +575,19 @@ with gr.Blocks(title="GVFD Navigator", theme=gr.themes.Soft()) as demo:
|
|
| 578 |
# Then pass the filtered dataframe to all visualization functions
|
| 579 |
return (
|
| 580 |
get_data_table(filtered_df),
|
| 581 |
-
get_summary_stats(filtered_df),
|
| 582 |
create_bar_chart(filtered_df),
|
| 583 |
create_map_visualization(filtered_df),
|
| 584 |
create_comparison_chart(filtered_df),
|
| 585 |
create_box_plot(filtered_df)
|
| 586 |
)
|
| 587 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 588 |
# Wire up the unified filter button
|
| 589 |
refresh_btn.click(
|
| 590 |
fn=update_all,
|
|
@@ -599,7 +602,7 @@ with gr.Blocks(title="GVFD Navigator", theme=gr.themes.Soft()) as demo:
|
|
| 599 |
min_value,
|
| 600 |
max_value
|
| 601 |
],
|
| 602 |
-
outputs=[data_table,
|
| 603 |
)
|
| 604 |
|
| 605 |
if __name__ == "__main__":
|
|
|
|
| 43 |
return sorted(df['topic'].dropna().unique().tolist())
|
| 44 |
return []
|
| 45 |
|
| 46 |
+
def get_specific_categories(topics=None):
|
| 47 |
+
"""Get unique specific categories filtered by topics"""
|
| 48 |
if df.empty:
|
| 49 |
return []
|
| 50 |
+
|
| 51 |
+
filtered_df = df
|
| 52 |
+
if topics and len(topics) > 0:
|
| 53 |
+
filtered_df = df[df['topic'].isin(topics)]
|
| 54 |
+
|
| 55 |
+
if 'category' in filtered_df.columns:
|
| 56 |
+
return sorted(filtered_df['category'].dropna().unique().tolist())
|
| 57 |
return []
|
| 58 |
|
| 59 |
+
def get_locations(topics=None):
|
| 60 |
+
"""Get unique locations filtered by topics"""
|
| 61 |
if df.empty:
|
| 62 |
return []
|
| 63 |
+
|
| 64 |
+
filtered_df = df
|
| 65 |
+
if topics and len(topics) > 0:
|
| 66 |
+
filtered_df = df[df['topic'].isin(topics)]
|
| 67 |
+
|
| 68 |
+
if 'location' in filtered_df.columns:
|
| 69 |
+
return sorted(filtered_df['location'].dropna().unique().tolist())
|
| 70 |
return []
|
| 71 |
|
| 72 |
+
def get_impacts(topics=None):
|
| 73 |
+
"""Get unique impact types filtered by topics"""
|
| 74 |
if df.empty:
|
| 75 |
return []
|
| 76 |
+
|
| 77 |
+
filtered_df = df
|
| 78 |
+
if topics and len(topics) > 0:
|
| 79 |
+
filtered_df = df[df['topic'].isin(topics)]
|
| 80 |
+
|
| 81 |
+
if 'impact' in filtered_df.columns:
|
| 82 |
+
return sorted(filtered_df['impact'].dropna().unique().tolist())
|
| 83 |
return []
|
| 84 |
|
| 85 |
def get_regions():
|
|
|
|
| 279 |
fig.update_layout(xaxis_tickangle=-45, height=600)
|
| 280 |
return fig
|
| 281 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 282 |
|
| 283 |
def get_data_table(filtered_df, max_rows=1000):
|
| 284 |
"""Return filtered data as a dataframe with formatted values"""
|
|
|
|
| 394 |
column_widths=["10%", "12%", "12%", "12%", "12%", "10%", "12%", "10%", "10%"]
|
| 395 |
)
|
| 396 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 397 |
# Visualizations below the table
|
| 398 |
gr.Markdown("## Visualizations")
|
| 399 |
gr.Markdown("The charts and maps below reflect your filtered data selection from above.")
|
|
|
|
| 549 |
""")
|
| 550 |
|
| 551 |
# Event handlers
|
| 552 |
+
def update_dropdowns_on_topic_change(topics):
|
| 553 |
+
"""Update category, location, and impact dropdowns based on selected topics"""
|
| 554 |
+
return (
|
| 555 |
+
gr.Dropdown(choices=get_specific_categories(topics), value=None),
|
| 556 |
+
gr.Dropdown(choices=get_locations(topics), value=None),
|
| 557 |
+
gr.Dropdown(choices=get_impacts(topics), value=None)
|
| 558 |
+
)
|
| 559 |
+
|
| 560 |
def update_all(search, countries, topics, categories, locations, impacts, regions, min_val, max_val):
|
| 561 |
"""Update all views when filters are applied"""
|
| 562 |
# First filter the data
|
|
|
|
| 575 |
# Then pass the filtered dataframe to all visualization functions
|
| 576 |
return (
|
| 577 |
get_data_table(filtered_df),
|
|
|
|
| 578 |
create_bar_chart(filtered_df),
|
| 579 |
create_map_visualization(filtered_df),
|
| 580 |
create_comparison_chart(filtered_df),
|
| 581 |
create_box_plot(filtered_df)
|
| 582 |
)
|
| 583 |
|
| 584 |
+
# Wire up topic selector to update dependent dropdowns
|
| 585 |
+
topic_selector.change(
|
| 586 |
+
fn=update_dropdowns_on_topic_change,
|
| 587 |
+
inputs=[topic_selector],
|
| 588 |
+
outputs=[category_selector, location_selector, impact_selector]
|
| 589 |
+
)
|
| 590 |
+
|
| 591 |
# Wire up the unified filter button
|
| 592 |
refresh_btn.click(
|
| 593 |
fn=update_all,
|
|
|
|
| 602 |
min_value,
|
| 603 |
max_value
|
| 604 |
],
|
| 605 |
+
outputs=[data_table, bar_chart, map_chart, comparison_chart, box_plot]
|
| 606 |
)
|
| 607 |
|
| 608 |
if __name__ == "__main__":
|