Spaces:
Running
Running
import pandas as pd | |
import plotly.graph_objects as go | |
from streamlit_option_menu import option_menu | |
import streamlit as st | |
from streamlit_extras.stylable_container import stylable_container | |
st.title("Crescimento populacional - UBS Flamengo") | |
with stylable_container( | |
key="banner", | |
css_styles=""" | |
img { | |
width: 1800px; | |
height: 340px; | |
overflow: hidden; | |
position: relative; | |
object-fit: cover; | |
border-radius: 20px; /* Adiciona bordas arredondadas */ | |
mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0)); | |
-webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0)); /* For Safari */ | |
} | |
""", | |
): | |
st.image("pop.jpg") | |
st.title("Crescimento populacional - UBS Flamengo") | |
raw_data = [ | |
{"Mês": "mai-21", "Usuários": 3402, "Domicílios": 1440, "Famílias": 1269}, | |
{"Mês": "jun-21", "Usuários": 3503, "Domicílios": 1462, "Famílias": 1304}, | |
{"Mês": "jul-21", "Usuários": 3559, "Domicílios": 1478, "Famílias": 1323}, | |
{"Mês": "ago-21", "Usuários": 3592, "Domicílios": 1490, "Famílias": 1338}, | |
{"Mês": "set-21", "Usuários": 3755, "Domicílios": 1573, "Famílias": 1380}, | |
{"Mês": "out-21", "Usuários": 3776, "Domicílios": 1533, "Famílias": 1384}, | |
{"Mês": "nov-21", "Usuários": 3839, "Domicílios": 1553, "Famílias": 1397}, | |
{"Mês": "dez-21", "Usuários": 3926, "Domicílios": 1581, "Famílias": 1423}, | |
{"Mês": "jan-22", "Usuários": 3951, "Domicílios": 1596, "Famílias": 1437}, | |
{"Mês": "fev-22", "Usuários": 4035, "Domicílios": 1638, "Famílias": 1465}, | |
{"Mês": "mar-22", "Usuários": 4131, "Domicílios": 1672, "Famílias": 1500}, | |
{"Mês": "abr-22", "Usuários": 4306, "Domicílios": 1723, "Famílias": 1555}, | |
{"Mês": "mai-22", "Usuários": 4553, "Domicílios": 1795, "Famílias": 1625}, | |
{"Mês": "jun-22", "Usuários": 4639, "Domicílios": 1817, "Famílias": 1653}, | |
{"Mês": "jul-22", "Usuários": 4719, "Domicílios": 1848, "Famílias": 1676}, | |
{"Mês": "ago-22", "Usuários": 4776, "Domicílios": 1869, "Famílias": 1687}, | |
{"Mês": "set-22", "Usuários": 4831, "Domicílios": 1883, "Famílias": 1699}, | |
{"Mês": "out-22", "Usuários": 4871, "Domicílios": 1900, "Famílias": 1709}, | |
{"Mês": "nov-22", "Usuários": 4874, "Domicílios": 1906, "Famílias": 1708}, | |
{"Mês": "dez-22", "Usuários": 4920, "Domicílios": 1914, "Famílias": 1720}, | |
{"Mês": "jan-23", "Usuários": 5135, "Domicílios": 2006, "Famílias": 1776}, | |
{"Mês": "fev-23", "Usuários": 5396, "Domicílios": 2084, "Famílias": 1848}, | |
{"Mês": "mar-23", "Usuários": 5544, "Domicílios": 2127, "Famílias": 1893}, | |
{"Mês": "abr-23", "Usuários": 5546, "Domicílios": 2140, "Famílias": 1910}, | |
{"Mês": "mai-23", "Usuários": 5579, "Domicílios": 2164, "Famílias": 1920}, | |
{"Mês": "jun-23", "Usuários": 5642, "Domicílios": 2181, "Famílias": 1946}, | |
{"Mês": "jul-23", "Usuários": 5681, "Domicílios": 2200, "Famílias": 1961}, | |
{"Mês": "ago-23", "Usuários": 5728, "Domicílios": 2208, "Famílias": 1972}, | |
{"Mês": "set-23", "Usuários": 5774, "Domicílios": 2228, "Famílias": 1983}, | |
{"Mês": "out-23", "Usuários": 5841, "Domicílios": 2245, "Famílias": 2007}, | |
{"Mês": "nov-23", "Usuários": 5891, "Domicílios": 2297, "Famílias": 2027}, | |
{"Mês": "dez-23", "Usuários": 5933, "Domicílios": 2281, "Famílias": 2036}, | |
{"Mês": "jan-24", "Usuários": 5982, "Domicílios": 2307, "Famílias": 2050}, | |
{"Mês": "fev-24", "Usuários": 6005, "Domicílios": 2333, "Famílias": 2057}, | |
{"Mês": "mar-24", "Usuários": 6020, "Domicílios": 2327, "Famílias": 2070}, | |
{"Mês": "abr-24", "Usuários": 6074, "Domicílios": 2370, "Famílias": 2095}, | |
] | |
df = pd.DataFrame(raw_data) | |
def processar_dados(dados, intervalo): | |
""" | |
Process data based on the specified interval and return the aggregated data. | |
Parameters: | |
- dados: List of dictionaries containing data for each month. | |
- intervalo: String indicating the interval for data aggregation. | |
Returns: | |
- List of dictionaries with aggregated data based on the specified interval. | |
""" | |
if intervalo == "Mensal": | |
return dados | |
agrupamentos = {"Trimestral": 3, "Semestral": 6, "Anual": 12} | |
dados_agrupados = [] | |
for i in range(0, len(dados), agrupamentos[intervalo]): | |
grupo = dados[i : i + agrupamentos[intervalo]] | |
ultimo_Mês = grupo[-1]["Mês"] | |
dados_agrupados.append( | |
{ | |
"Mês": ultimo_Mês, | |
"Usuários": max(d["Usuários"] for d in grupo), | |
"Domicílios": max(d["Domicílios"] for d in grupo), | |
"Famílias": max(d["Famílias"] for d in grupo), | |
} | |
) | |
return dados_agrupados | |
def formatar_data(Mês): | |
""" | |
A function that formats the data based on the input Mês parameter. | |
Parameters: | |
- Mês (str): A string containing the month and year separated by a hyphen. | |
Returns: | |
- str: A formatted string in the format "month/year". | |
""" | |
m, a = Mês.split("-") | |
return f"{m}/{a}" | |
# Adicionando estilo personalizado | |
st.markdown( | |
""" | |
<style> | |
.stSelectbox [data-baseweb="select"] { | |
max-width: 300px; | |
} | |
.st-emotion-cache-16idsys p { | |
font-size: 20px; | |
font-weight: bold; | |
color: #4FCBFC; | |
} | |
</style> | |
""", | |
unsafe_allow_html=True, | |
) | |
# Criando duas colunas para os menus de opções | |
col1, col2, col3 = st.columns([3, 2, 2]) | |
with col1: | |
st.dataframe(df, use_container_width=True, height= 250, hide_index=True) | |
with col2: | |
intervalo = option_menu( | |
"Intervalo de Tempo", | |
["Mensal", "Trimestral", "Semestral", "Anual"], | |
icons=["calendar-month", "calendar-quarter", "calendar-half", "calendar-year"], | |
menu_icon="cast", | |
default_index=0, | |
styles={ | |
"container": {"padding": "0!important", "background-color": "#262730"}, | |
"icon": {"color": "#4FCBFC", "font-size": "18px"}, | |
"nav-link": { | |
"font-size": "14px", | |
"text-align": "center", | |
"margin": "0px", | |
"padding": "10px", | |
"--hover-color": "#363940", | |
"color": "#FFFFFF", | |
}, | |
"nav-link-selected": {"background-color": "#0083B8"}, | |
"separator": {"border-color": "#4B4B4B"}, | |
}, | |
) | |
with col3: | |
metrica = option_menu( | |
"Métrica", | |
["Todos", "Usuários", "Domicílios", "Famílias"], | |
icons=["list", "person", "house", "people"], | |
menu_icon="cast", | |
default_index=0, | |
styles={ | |
"container": {"padding": "0!important", "background-color": "#262730"}, | |
"icon": {"color": "#4FCBFC", "font-size": "18px"}, | |
"nav-link": { | |
"font-size": "14px", | |
"text-align": "center", | |
"margin": "0px", | |
"padding": "10px", | |
"--hover-color": "#363940", | |
"color": "#FFFFFF", | |
}, | |
"nav-link-selected": {"background-color": "#0083B8"}, | |
"separator": {"border-color": "#4B4B4B"}, | |
}, | |
) | |
dados_processados = processar_dados(raw_data, intervalo) | |
# Switch para mostrar valores nos pontos | |
mostrar_valores = st.checkbox("Mostrar valores nos pontos", value=True) | |
# Criação do gráfico | |
fig = go.Figure() | |
metricas = ["Usuários", "Domicílios", "Famílias"] if metrica == "Todos" else [metrica] | |
cores = {"Usuários": "#1f77b4", "Domicílios": "#ff7f0e", "Famílias": "#2ca02c"} | |
# Slider Component | |
st.sidebar.header("Ajustes dos Balões") | |
balloon_positions = {} | |
for m in metricas: | |
balloon_positions[m] = st.sidebar.slider( | |
f"Posição do balão para {m}", min_value=-100, max_value=0, value=-40, step=5 | |
) | |
annotations = [] | |
for m in metricas: | |
x_data = [formatar_data(d["Mês"]) for d in dados_processados] | |
y_data = [d[m] for d in dados_processados] | |
fig.add_trace( | |
go.Scatter( | |
x=x_data, | |
y=y_data, | |
mode="lines+markers", | |
name=m, | |
line=dict(color=cores[m], width=3), | |
marker=dict(size=8, symbol="circle", line=dict(width=2, color="white")), | |
) | |
) | |
if mostrar_valores: | |
for i, (x, y) in enumerate(zip(x_data, y_data)): | |
annotations.append( | |
dict( | |
x=x, | |
y=y, | |
xref="x", | |
yref="y", | |
text=f"{y:,.0f}", | |
showarrow=True, | |
arrowhead=7, | |
ax=0, | |
ay=balloon_positions[m], # Usa a posição ajustada para cada métrica | |
bgcolor=cores[m], | |
opacity=0.8, | |
bordercolor="white", | |
borderwidth=2, | |
borderpad=4, | |
font=dict(color="white", size=10), | |
) | |
) | |
fig.update_layout( | |
title={ | |
"text": "Crescimento na Área de Saúde", | |
"y": 0.95, | |
"x": 0.5, | |
"xanchor": "center", | |
"yanchor": "top", | |
"font": dict(size=24, color="#4FCBFC"), | |
}, | |
xaxis_title="Mês", | |
yaxis_title="Quantidade", | |
legend_title="Métricas", | |
template="plotly_dark", | |
plot_bgcolor="#262730", | |
paper_bgcolor="#262730", | |
font=dict(color="white"), | |
xaxis=dict(showgrid=True, gridcolor="#4B4B4B", tickangle=45), | |
yaxis=dict(showgrid=True, gridcolor="#4B4B4B"), | |
legend=dict( | |
bgcolor="rgba(0,0,0,0)", | |
bordercolor="rgba(0,0,0,0)", | |
font=dict(size=12, color="white"), | |
), | |
margin=dict(l=50, r=50, t=80, b=50), | |
annotations=annotations, | |
) | |
st.plotly_chart(fig, use_container_width=True) | |