|
|
import dash |
|
|
import dash_mantine_components as dmc |
|
|
import plotly.express as px |
|
|
from dash import Input, Output, callback, dcc, html |
|
|
from dash_iconify import DashIconify |
|
|
|
|
|
|
|
|
app = dash.Dash(__name__) |
|
|
server = app.server |
|
|
|
|
|
df = px.data.gapminder() |
|
|
|
|
|
|
|
|
def create_scatter_plot(selected_year, selected_continent=None): |
|
|
filtered_df = df[df["year"] == selected_year] |
|
|
|
|
|
if selected_continent and selected_continent != "All": |
|
|
filtered_df = filtered_df[filtered_df["continent"] == selected_continent] |
|
|
|
|
|
fig = px.scatter( |
|
|
filtered_df, |
|
|
x="gdpPercap", |
|
|
y="lifeExp", |
|
|
size="pop", |
|
|
color="continent", |
|
|
hover_name="country", |
|
|
log_x=True, |
|
|
size_max=60, |
|
|
title=f"Life Expectancy vs GDP per Capita ({selected_year})", |
|
|
) |
|
|
|
|
|
fig.update_layout( |
|
|
template="plotly_dark", |
|
|
paper_bgcolor="rgba(0,0,0,0)", |
|
|
plot_bgcolor="rgba(0,0,0,0)", |
|
|
) |
|
|
|
|
|
return fig |
|
|
|
|
|
|
|
|
def create_line_chart(selected_country): |
|
|
country_data = df[df["country"] == selected_country] |
|
|
fig = px.line( |
|
|
country_data, |
|
|
x="year", |
|
|
y="lifeExp", |
|
|
title=f"{selected_country} - Life Expectancy", |
|
|
) |
|
|
fig.update_layout( |
|
|
template="plotly_dark", |
|
|
paper_bgcolor="rgba(0,0,0,0)", |
|
|
plot_bgcolor="rgba(0,0,0,0)", |
|
|
) |
|
|
return fig |
|
|
|
|
|
|
|
|
def create_bar_chart(selected_year): |
|
|
year_data = df[df["year"] == selected_year] |
|
|
continent_stats = year_data.groupby("continent")["lifeExp"].mean().reset_index() |
|
|
fig = px.bar( |
|
|
continent_stats, |
|
|
x="continent", |
|
|
y="lifeExp", |
|
|
color="continent", |
|
|
title=f"Average Life Expectancy by Continent ({selected_year})", |
|
|
) |
|
|
fig.update_layout( |
|
|
template="plotly_dark", |
|
|
paper_bgcolor="rgba(0,0,0,0)", |
|
|
plot_bgcolor="rgba(0,0,0,0)", |
|
|
showlegend=False, |
|
|
) |
|
|
return fig |
|
|
|
|
|
|
|
|
def create_datacard(title, value, icon, color): |
|
|
return dmc.Card( |
|
|
[ |
|
|
dmc.Group( |
|
|
[ |
|
|
DashIconify(icon=icon, width=30, color=color), |
|
|
html.Div( |
|
|
[ |
|
|
dmc.Text(value, size="xl", fw=700, c="white"), |
|
|
dmc.Text(title, size="sm", c="dimmed"), |
|
|
] |
|
|
), |
|
|
], |
|
|
align="center", |
|
|
gap="md", |
|
|
) |
|
|
], |
|
|
p="md", |
|
|
className="datacard", |
|
|
) |
|
|
|
|
|
|
|
|
app.layout = dmc.MantineProvider( |
|
|
[ |
|
|
html.Link( |
|
|
href="https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap", |
|
|
rel="stylesheet", |
|
|
), |
|
|
dmc.Group( |
|
|
[ |
|
|
DashIconify(icon="twemoji:globe-with-meridians", width=45), |
|
|
dmc.Text( |
|
|
"Gapminder World Data Explorer", ml=10, size="xl", fw=900, c="white" |
|
|
), |
|
|
], |
|
|
align="center", |
|
|
className="header", |
|
|
mb="md", |
|
|
), |
|
|
dmc.Grid( |
|
|
[ |
|
|
dmc.GridCol( |
|
|
[ |
|
|
dmc.Stack( |
|
|
[ |
|
|
dmc.Card( |
|
|
[ |
|
|
dmc.Text("Controls", size="lg", mb="md"), |
|
|
dmc.Stack( |
|
|
[ |
|
|
html.Div( |
|
|
[ |
|
|
dmc.Text( |
|
|
"Year:", size="sm", mb=5 |
|
|
), |
|
|
dmc.Slider( |
|
|
id="year-slider", |
|
|
min=1952, |
|
|
max=2007, |
|
|
step=5, |
|
|
value=2007, |
|
|
marks=[ |
|
|
{ |
|
|
"value": year, |
|
|
"label": str(year), |
|
|
} |
|
|
for year in [ |
|
|
1952, |
|
|
1967, |
|
|
1982, |
|
|
1997, |
|
|
2007, |
|
|
] |
|
|
], |
|
|
), |
|
|
] |
|
|
), |
|
|
html.Div( |
|
|
[ |
|
|
dmc.Text( |
|
|
"Continent Filter:", |
|
|
size="sm", |
|
|
mb=5, |
|
|
), |
|
|
dmc.Select( |
|
|
id="continent-dropdown", |
|
|
data=[ |
|
|
{ |
|
|
"value": "All", |
|
|
"label": "All Continents", |
|
|
} |
|
|
] |
|
|
+ [ |
|
|
{ |
|
|
"value": cont, |
|
|
"label": cont, |
|
|
} |
|
|
for cont in sorted( |
|
|
df[ |
|
|
"continent" |
|
|
].unique() |
|
|
) |
|
|
], |
|
|
value="All", |
|
|
), |
|
|
] |
|
|
), |
|
|
html.Div( |
|
|
[ |
|
|
dmc.Text( |
|
|
"Select Country:", |
|
|
size="sm", |
|
|
mb=5, |
|
|
), |
|
|
dmc.Select( |
|
|
id="country-dropdown", |
|
|
data=[ |
|
|
{ |
|
|
"value": country, |
|
|
"label": country, |
|
|
} |
|
|
for country in sorted( |
|
|
df[ |
|
|
"country" |
|
|
].unique() |
|
|
) |
|
|
], |
|
|
value="United States", |
|
|
searchable=True, |
|
|
), |
|
|
] |
|
|
), |
|
|
], |
|
|
gap="lg", |
|
|
), |
|
|
], |
|
|
p="md", |
|
|
className="control-card", |
|
|
) |
|
|
] |
|
|
) |
|
|
], |
|
|
span=3, |
|
|
), |
|
|
dmc.GridCol( |
|
|
[ |
|
|
dmc.Stack( |
|
|
[ |
|
|
html.Div(id="stats-cards"), |
|
|
dmc.Card( |
|
|
[dcc.Graph(id="scatter-plot")], |
|
|
p="sm", |
|
|
className="chart-card", |
|
|
), |
|
|
], |
|
|
gap="md", |
|
|
) |
|
|
], |
|
|
span=9, |
|
|
), |
|
|
], |
|
|
gutter="md", |
|
|
), |
|
|
dmc.Grid( |
|
|
[ |
|
|
dmc.GridCol( |
|
|
[ |
|
|
dmc.Card( |
|
|
[dcc.Graph(id="line-chart")], p="sm", className="chart-card" |
|
|
) |
|
|
], |
|
|
span=6, |
|
|
), |
|
|
dmc.GridCol( |
|
|
[ |
|
|
dmc.Card( |
|
|
[dcc.Graph(id="bar-chart")], p="sm", className="chart-card" |
|
|
) |
|
|
], |
|
|
span=6, |
|
|
), |
|
|
], |
|
|
gutter="md", |
|
|
mt="md", |
|
|
), |
|
|
], |
|
|
forceColorScheme="dark", |
|
|
theme={"colorScheme": "dark"}, |
|
|
) |
|
|
|
|
|
|
|
|
@callback( |
|
|
Output("scatter-plot", "figure"), |
|
|
[Input("year-slider", "value"), Input("continent-dropdown", "value")], |
|
|
) |
|
|
def update_scatter_plot(selected_year, selected_continent): |
|
|
return create_scatter_plot(selected_year, selected_continent) |
|
|
|
|
|
|
|
|
@callback(Output("line-chart", "figure"), Input("country-dropdown", "value")) |
|
|
def update_line_chart(selected_country): |
|
|
return create_line_chart(selected_country) |
|
|
|
|
|
|
|
|
@callback(Output("bar-chart", "figure"), Input("year-slider", "value")) |
|
|
def update_bar_chart(selected_year): |
|
|
return create_bar_chart(selected_year) |
|
|
|
|
|
|
|
|
@callback(Output("stats-cards", "children"), Input("year-slider", "value")) |
|
|
def update_stats(selected_year): |
|
|
year_data = df[df["year"] == selected_year] |
|
|
|
|
|
avg_life_exp = round(year_data["lifeExp"].mean(), 1) |
|
|
total_pop = year_data["pop"].sum() |
|
|
num_countries = len(year_data) |
|
|
avg_gdp = round(year_data["gdpPercap"].mean(), 0) |
|
|
|
|
|
return dmc.Grid( |
|
|
[ |
|
|
dmc.GridCol( |
|
|
create_datacard( |
|
|
"Life Expectancy", |
|
|
f"{avg_life_exp} years", |
|
|
"mdi:heart-pulse", |
|
|
"#ff6b35", |
|
|
), |
|
|
span=3, |
|
|
), |
|
|
dmc.GridCol( |
|
|
create_datacard( |
|
|
"Population", |
|
|
f"{total_pop / 1e9:.1f}B", |
|
|
"mdi:account-group", |
|
|
"#1f77b4", |
|
|
), |
|
|
span=3, |
|
|
), |
|
|
dmc.GridCol( |
|
|
create_datacard( |
|
|
"Countries", str(num_countries), "mdi:earth", "#2ca02c" |
|
|
), |
|
|
span=3, |
|
|
), |
|
|
dmc.GridCol( |
|
|
create_datacard( |
|
|
"GDP per Capita", f"${avg_gdp:,.0f}", "mdi:currency-usd", "#d62728" |
|
|
), |
|
|
span=3, |
|
|
), |
|
|
], |
|
|
gutter="sm", |
|
|
) |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
app.run(debug=True, port=8050) |
|
|
|