import dash
from dash import html, dcc
import pandas as pd
import plotly.graph_objects as go
import dash_bootstrap_components as dbc
from dash_bootstrap_templates import load_figure_template
# Data prep
data = {
'Country': ['USA', 'Argentina', 'UK', 'Australia', 'Turkey', 'Belgium', 'Sweden', 'Brazil', 'Spain', 'Canada',
'South Korea', 'Russia', 'Czech Republic', 'China', 'Poland', 'France', 'Netherlands', 'Germany',
'Mexico', 'Hong Kong', 'Japan', 'Italy'],
'Dog': [50, 66, 27, 39, 12, 29, 22, 58, 37, 33, 20, 29, 38, 25, 45, 29, 25, 21, 64, 14, 17, 39],
'Cat': [39, 32, 27, 29, 15, 33, 28, 28, 23, 35, 6, 57, 26, 10, 32, 41, 26, 29, 24, 10, 14, 34],
'Fish': [11, 8, 9, 13, 16, 15, 6, 7, 9, 9, 7, 11, 14, 17, 12, 12, 11, 9, 10, 14, 9, 11],
'Bird': [6, 7, 4, 10, 20, 8, 3, 11, 11, 4, 1, 9, 8, 5, 7, 5, 7, 6, 10, 5, 2, 8],
}
country_to_continent = {
"USA": "North America",
"Argentina": "South America",
"UK": "Europe",
"Australia": "Oceania",
"Turkey": "Europe",
"Belgium": "Europe",
"Sweden": "Europe",
"Brazil": "South America",
"Spain": "Europe",
"Canada": "North America",
"South Korea": "Asia",
"Russia": "Europe",
"Czech Republic": "Europe",
"China": "Asia",
"Poland": "Europe",
"France": "Europe",
"Netherlands": "Europe",
"Germany": "Europe",
"Mexico": "North America",
"Hong Kong": "Asia",
"Japan": "Asia",
"Italy": "Europe"
}
animals = ['Dog', 'Cat', 'Fish', 'Bird']
animal_filenames = {'Dog': 'dog', 'Cat': 'cat', 'Fish': 'fish', 'Bird': 'bird'}
df = pd.DataFrame(data)
df['Continent'] = df['Country'].map(country_to_continent)
means = df.groupby('Continent')[animals].mean().reset_index()
means = means.sort_values('Continent').reset_index(drop=True)
continent_names = means['Continent'].tolist()
# Generate the Countries per continent paragraph
continent_counts = df.groupby('Continent')['Country'].nunique().to_dict()
# To keep the same order as in your plot:
ordered_counts = [f"{cont} ({continent_counts.get(cont, 0)})" for cont in continent_names]
continent_text = "This visual is based on the data of 22 countries divided as follows: " + ", ".join(ordered_counts)
colors = ["#ad3b02", "#ce4602"]
fig = go.Figure()
# Draw alternating background rectangles per continent
for i, continent in enumerate(continent_names):
fig.add_shape(
type="rect",
x0=i - 0.49, x1=i + 0.49,
y0=0, y1=100,
xref="x", yref="y",
fillcolor=colors[i % 2],
opacity=0.42,
layer="below",
line_width=0,
)
# For each continent, put all animal icons (and labels!) at the same x
icon_size = 5 # percent units, since y is percentage
for i, row in means.iterrows():
for j, animal in enumerate(animals):
y_val = row[animal]
x_val = i
# Animal icon
fig.add_layout_image(dict(
source=f"assets/images/{animal_filenames[animal]}.png",
x=x_val,
y=y_val,
xref="x", yref="y",
xanchor="center", yanchor="middle",
sizex=0.27, sizey=icon_size,
sizing='contain',
layer="above",
opacity=.4
))
# LEFT OF IMAGE: Text annotation
text_x_offset = 0.18 # tweak for padding
fig.add_annotation(
x=x_val - text_x_offset,
y=y_val,
text=f'<b>{int(round(y_val))}%</b>',
showarrow=False,
font=dict(size=16, color="white", family='"Indie Flower", cursive'),
xanchor="right",
yanchor="middle"
)
# X & Y axis styling
fig.update_xaxes(
showgrid=False, zeroline=False,
linecolor="#202020", # Make axis line the background color (hidden)
showline=False,
tickvals=list(range(len(continent_names))),
ticktext=[f"<b>{c}</b>" for c in continent_names],
tickfont=dict(size=26, color="white", family='"Indie Flower", cursive'),
range=[-0.7, len(continent_names) - 0.3]
)
fig.update_yaxes(
showgrid=False, zeroline=False,
color='rgba(0,0,0,0)',
range=[0, 70], # y-axis from 0% to 80%
tickvals=[0, 20, 40, 60, 80],
ticktext=["0%", "20%", "40%", "60%", "80%"],
showticklabels=False
)
fig.update_layout(
plot_bgcolor="#202020",
paper_bgcolor="#202020",
margin=dict(t=60, l=60, r=60, b=60),
xaxis_title=None, yaxis_title=None,
height=700,
#width = 1000
)
# Dash app layout
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.CYBORG])
app.layout = dbc.Container ([ html.Div([
html.H1("Average percentage of households who own a dog, cat, fish or bird by continent",
style={ 'color': 'white',
"textAlign": "center",
'fontFamily': '"Indie Flower", cursive'}),
dcc.Graph(figure=fig, config={"displayModeBar": False}),
html.P(continent_text,
style={
"color": "white",
"fontFamily": '"Indie Flower", cursive',
"textAlign": "center",
"fontSize": "1.25em",
"marginTop": "16px"
}),
], style={"background": "#202020", "minHeight": "100vh", "padding": "20px"})
])
if __name__ == "__main__":
app.run(debug=True)