import folium
import geopandas as gpd
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import streamlit as st
from branca.colormap import LinearColormap
from folium.plugins import HeatMap
from streamlit_extras.add_vertical_space import add_vertical_space
from streamlit_extras.stylable_container import stylable_container
from streamlit_folium import folium_static
from streamlit_option_menu import option_menu
with stylable_container(
key="banner",
css_styles="""
img {
width: 1800px;
height: 250px;
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("src/Images/mp.jpg")
add_vertical_space(2)
st.markdown(""" ### :world_map: **UBS Flamengo: (IBGE 2022)** """)
@st.cache_resource
def load_data():
"""
A function that loads and reads geojson data for UBS Flamengo and
converts it to the specified coordinate reference system.
"""
return gpd.read_file("views/flamengo_ibge2022.geojson").to_crs(epsg=4326)
gdf = load_data()
LATITUDE = -19.965591804
LONGITUDE = -44.057912815
lat = -19.96214
long = -44.05603
total_pop = gdf["População"].sum()
num_setores = len(gdf)
col1, col2, col3 = st.columns([1, 1, 5])
STYLE = "static/style.css"
STYLES = "static/styles.html"
with open(STYLE, "r", encoding="utf-8") as f:
st.markdown(f"", unsafe_allow_html=True)
with open(STYLES, "r", encoding="utf-8") as f:
st.markdown(f"", unsafe_allow_html=True)
with st.expander("Visualização", expanded=True):
selected_tab = option_menu(
menu_title=None,
options=[
"Mapa IBGE",
"Equipe Azul",
"Equipe Vermelha",
],
icons=["person", "geo-alt", "capsule-pill"],
menu_icon="cast",
default_index=0,
orientation="horizontal",
styles={
"container": {
"padding": "5px",
"background-color": "#1E1E28",
"border-radius": "8px",
},
"icon": {
"color": "#64B5F6",
"font-size": "20px",
"padding-right": "8px",
},
"nav-link": {
"font-size": "16px",
"text-align": "center",
"margin": "5px",
"padding": "12px",
"background-color": "#2A2B3D",
"--hover-color": "#4B4B4B",
"color": "#FFFFFF",
"border-radius": "4px",
},
"nav-link-selected": {
"background-color": "#007BB5",
"color": "#FFFFFF",
"font-weight": "bold",
},
"separator": {
"border-color": "#303030",
"margin": "0 10px",
},
},
)
if selected_tab == "Mapa IBGE":
col1, col2, col3, col4, col5 = st.columns([1.5, 1.5, 0.8, 5, 0.5])
with col1:
st.metric(label="👪 População Total",
value=f"{total_pop:,} habitantes",
help="Dados do Censo 2022 IBGE")
map_type = st.selectbox("Tipo de mapa",
["População", "Densidade", "Heatmap"])
with col2:
st.metric(label="🗺️ Número de Setores Censitários",
value=f"{num_setores}",
help="Dados do Censo 2022 IBGE")
base_map = st.selectbox("Mapa base",
["Cartodb Positron", "OpenStreetMap"])
with col4, st.container(border=False, height=400):
row1, row2, row3 = st.columns([0.5, 3, 0.9])
with row1:
st.write('')
with row2:
st.write("""
### Definição de Setor Censitário
É a menor unidade territorial utilizada pelo IBGE para a coleta de dados em censos
demográficos. Cada setor é delimitado por características físicas e populacionais.
Geralmente contém entre 250 e 350 domicílios.
Fundamentais em pesquisas, elaboração de políticas públicas, planejamento urbano,
e atividades que dependem de informações demográficas precisas.
Permitem uma análise granular da distribuição populacional, socioeconômica e das
condições de moradia. É fundamental .
""")
with row3:
st.write('')
add_vertical_space(3)
col1, col2 = st.columns(2)
with col1:
m = folium.Map(location=[LATITUDE, LONGITUDE],
tiles=base_map,
zoom_start=15)
dns_p = "Densidade pop. (hab/km²) UBS Flamengo - IBGE 2022"
if map_type in ["População", "Densidade"]:
if map_type == "População":
column = "População"
caption = "Pop. residente UBS Flamengo IBGE 2022"
else:
gdf["DENSIDADE"] = gdf["População"] / gdf["Área em km²"]
column = "DENSIDADE"
caption = dns_p
colorscale = px.colors.sequential.Viridis
colormap = LinearColormap(
colors=colorscale,
vmin=gdf[column].min(),
vmax=gdf[column].max(),
caption=caption,
)
folium.GeoJson(
gdf,
style_function=lambda feature: {
"fillColor": colormap(feature["properties"][column]),
"color": "black",
"weight": 1,
"fillOpacity": 0.6,
},
highlight_function=lambda feature: {
"fillColor": "#ffaf00",
"color": "green",
"weight": 3,
"fillOpacity": 0.9,
} if feature else {},
tooltip=folium.GeoJsonTooltip(
fields=["Setor", column, "Área em km²"],
aliases=[
"Setor Censitário:",
f"{caption}:",
"Área (km²):",
],
style=("background-color: white; color: #333333;"
"font-family: calibri; font-size: 12px;"
"padding: 10px;"),
),
).add_to(m)
colormap.add_to(m)
elif map_type == "Heatmap":
heat_data = [[
row["geometry"].centroid.y,
row["geometry"].centroid.x,
row["População"],
] for idx, row in gdf.iterrows()]
HeatMap(heat_data).add_to(m)
folium.Marker(
[lat, long],
popup="UBS Flamengo",
tooltip="UBS Flamengo",
icon=folium.Icon(color="red", icon="info-sign"),
).add_to(m)
STYLE_STATEMENT = (
"")
# folium.LayerControl().add_to(m) # Adding Layer Control is good practice.
# Display the map
folium_static(m)
# m.get_root().html.add_child(folium.Element(STYLE_STATEMENT))
# folium_static(m)
with col2:
fig = px.bar(
gdf,
x="Setor",
y="População",
title="Distribuição da População por Setor Censitário",
color="População",
color_continuous_scale=px.colors.sequential.Viridis,
)
st.plotly_chart(fig)
age_columns = [
"População_0A4",
"População_5A9",
"População_10A14",
"População_15A19",
"População_20A24",
"População_25A29",
"População_30A34",
"População_35A39",
"População_40A44",
"População_45A49",
"População_50A54",
"População_55A59",
"População_60A64",
"População_65A69",
"População_70A74",
"População_75A79",
"População_80A84",
"População_85A89",
"População_90A94",
"População_95A99",
"População_100OUMAIS",
]
fig = px.bar()
elif selected_tab == "Equipe Azul":
st.subheader("Crescimento populacional - UBS Flamengo - Equipe Azul")
with stylable_container(
key="exp1",
css_styles="""
img {
width: 200px;
height: 200px;
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("src/Images/blue.png", caption='Equipe Azul')
# st.image("src/Images/pop.jpg")
raw_data = [
{
"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": 5680,
"Domicílios": 2200,
"Famílias": 1961
},
{
"Mês": "ago-23",
"Usuários": 5727,
"Domicílios": 2208,
"Famílias": 1972
},
{
"Mês": "set-23",
"Usuários": 5772,
"Domicílios": 2228,
"Famílias": 1983
},
{
"Mês": "out-23",
"Usuários": 5839,
"Domicílios": 2245,
"Famílias": 2007
},
{
"Mês": "nov-23",
"Usuários": 5889,
"Domicílios": 2297,
"Famílias": 2027
},
{
"Mês": "dez-23",
"Usuários": 5932,
"Domicílios": 2281,
"Famílias": 2036
},
{
"Mês": "jan-24",
"Usuários": 5980,
"Domicílios": 2307,
"Famílias": 2050
},
{
"Mês": "fev-24",
"Usuários": 6003,
"Domicílios": 2333,
"Famílias": 2057
},
{
"Mês": "mar-24",
"Usuários": 6018,
"Domicílios": 2327,
"Famílias": 2070
},
{
"Mês": "abr-24",
"Usuários": 6072,
"Domicílios": 2370,
"Famílias": 2095
},
{
"Mês": "mai-24",
"Usuários": 6080,
"Domicílios": 2357,
"Famílias": 2097
},
{
"Mês": "jun-24",
"Usuários": 6112,
"Domicílios": 2372,
"Famílias": 2108
},
{
"Mês": "jul-24",
"Usuários": 6130,
"Domicílios": 2413,
"Famílias": 2110
},
{
"Mês": "ago-24",
"Usuários": 6169,
"Domicílios": 2397,
"Famílias": 2118
},
]
df = pd.DataFrame(raw_data)
@st.cache_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
@st.cache_data
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(
"""
""",
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": "#f0f0f3",
"border-radius": "15px",
"box-shadow":
"5px 5px 10px #d1d1d4, -5px -5px 10px #ffffff"
},
"icon": {
"color": "#007bff",
"font-size": "18px"
},
"nav-link": {
"font-size": "14px",
"text-align": "center",
"margin": "5px",
"padding": "10px",
"--hover-color": "#e6e6e9",
"color": "#333333",
"border-radius": "10px",
"transition": "all 0.3s ease",
},
"nav-link-selected": {
"background-color":
"#ffffff",
"box-shadow":
"inset 3px 3px 5px #d1d1d4, inset -3px -3px 5px #ffffff"
},
"separator": {
"border-color": "#e0e0e3"
},
},
)
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": "#f0f0f3",
"border-radius": "15px",
"box-shadow":
"5px 5px 10px #d1d1d4, -5px -5px 10px #ffffff"
},
"icon": {
"color": "#007bff",
"font-size": "18px"
},
"nav-link": {
"font-size": "14px",
"text-align": "center",
"margin": "5px",
"padding": "10px",
"--hover-color": "#e6e6e9",
"color": "#333333",
"border-radius": "10px",
"transition": "all 0.3s ease",
},
"nav-link-selected": {
"background-color":
"#ffffff",
"box-shadow":
"inset 3px 3px 5px #d1d1d4, inset -3px -3px 5px #ffffff"
},
"separator": {
"border-color": "#e0e0e3"
},
},
)
dados_processados = processar_dados(raw_data, intervalo)
# Criação do gráfico
fig = go.Figure()
metricas = ["Usuários", "Domicílios", "Famílias"
] if metrica == "Todos" else [metrica]
cores = {
"Usuários": "#007bff",
"Domicílios": "#28a745",
"Famílias": "#ffc107"
}
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={
"color": cores[m],
"width": 3
},
marker={
"size": 12,
"symbol": "circle",
"line": {
"width": 2,
"color": "white"
}
},
))
fig.update_layout(
hoverlabel={
"bgcolor": "white",
"font_size": 16,
"font_family": "Arial",
},
hovermode="x unified",
)
fig.update_traces(hovertemplate="%{y}
%{x}")
st.plotly_chart(fig, use_container_width=True)
elif selected_tab == "Equipe Vermelha":
st.subheader("Crescimento populacional - UBS Flamengo - Equipe Vermelha")
with stylable_container(
key="exp1",
css_styles="""
img {
width: 200px;
height: 200px;
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("src/Images/red.png", caption='Equipe Vermelha')
# st.image("src/Images/pop.jpg")
raw_red = [{
"Mês": "set-21",
"Usuários": 3542,
"Domicílios": 1243,
"Famílias": 1191
}, {
"Mês": "out-21",
"Usuários": 3647,
"Domicílios": 1240,
"Famílias": 1204
}, {
"Mês": "nov-21",
"Usuários": 3730,
"Domicílios": 1267,
"Famílias": 1227
}, {
"Mês": "dez-21",
"Usuários": 3847,
"Domicílios": 1307,
"Famílias": 1267
}, {
"Mês": "jan-22",
"Usuários": 3895,
"Domicílios": 1328,
"Famílias": 1284
}, {
"Mês": "fev-22",
"Usuários": 3937,
"Domicílios": 1342,
"Famílias": 1297
}, {
"Mês": "mar-22",
"Usuários": 4082,
"Domicílios": 1393,
"Famílias": 1348
}, {
"Mês": "abr-22",
"Usuários": 4248,
"Domicílios": 1434,
"Famílias": 1375
}, {
"Mês": "mai-22",
"Usuários": 4440,
"Domicílios": 1509,
"Famílias": 1442
}, {
"Mês": "jun-22",
"Usuários": 4646,
"Domicílios": 1575,
"Famílias": 1499
}, {
"Mês": "jul-22",
"Usuários": 4783,
"Domicílios": 1616,
"Famílias": 1539
}, {
"Mês": "ago-22",
"Usuários": 4909,
"Domicílios": 1670,
"Famílias": 1567
}, {
"Mês": "set-22",
"Usuários": 5008,
"Domicílios": 1720,
"Famílias": 1609
}, {
"Mês": "out-22",
"Usuários": 5017,
"Domicílios": 1721,
"Famílias": 1610
}, {
"Mês": "nov-22",
"Usuários": 5037,
"Domicílios": 1742,
"Famílias": 1613
}, {
"Mês": "dez-22",
"Usuários": 5060,
"Domicílios": 1742,
"Famílias": 1615
}, {
"Mês": "jan-23",
"Usuários": 5107,
"Domicílios": 1708,
"Famílias": 1563
}, {
"Mês": "fev-23",
"Usuários": 5127,
"Domicílios": 1631,
"Famílias": 1496
}, {
"Mês": "mar-23",
"Usuários": 5262,
"Domicílios": 1667,
"Famílias": 1533
}, {
"Mês": "abr-23",
"Usuários": 5279,
"Domicílios": 1682,
"Famílias": 1545
}, {
"Mês": "mai-23",
"Usuários": 5361,
"Domicílios": 1719,
"Famílias": 1575
}, {
"Mês": "jun-23",
"Usuários": 5381,
"Domicílios": 1728,
"Famílias": 1591
}, {
"Mês": "jul-23",
"Usuários": 5429,
"Domicílios": 1766,
"Famílias": 1609
}, {
"Mês": "ago-23",
"Usuários": 5417,
"Domicílios": 1743,
"Famílias": 1618
}, {
"Mês": "set-23",
"Usuários": 5447,
"Domicílios": 1748,
"Famílias": 1632
}, {
"Mês": "out-23",
"Usuários": 5495,
"Domicílios": 1772,
"Famílias": 1646
}, {
"Mês": "nov-23",
"Usuários": 5496,
"Domicílios": 1775,
"Famílias": 1650
}, {
"Mês": "dez-23",
"Usuários": 5519,
"Domicílios": 1767,
"Famílias": 1657
}, {
"Mês": "jan-24",
"Usuários": 5560,
"Domicílios": 1793,
"Famílias": 1673
}, {
"Mês": "fev-24",
"Usuários": 5574,
"Domicílios": 1795,
"Famílias": 1679
}, {
"Mês": "mar-24",
"Usuários": 5576,
"Domicílios": 1789,
"Famílias": 1676
}, {
"Mês": "abr-24",
"Usuários": 5624,
"Domicílios": 1824,
"Famílias": 1696
}, {
"Mês": "mai-24",
"Usuários": 5699,
"Domicílios": 1827,
"Famílias": 1713
}, {
"Mês": "jun-24",
"Usuários": 5739,
"Domicílios": 1843,
"Famílias": 1733
}, {
"Mês": "jul-24",
"Usuários": 5739,
"Domicílios": 1877,
"Famílias": 1742
}, {
"Mês": "ago-24",
"Usuários": 5760,
"Domicílios": 1881,
"Famílias": 1757
}]
df = pd.DataFrame(raw_red)
@st.cache_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
@st.cache_data
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(
"""
""",
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": "#f0f0f3",
"border-radius": "15px",
"box-shadow":
"5px 5px 10px #d1d1d4, -5px -5px 10px #ffffff"
},
"icon": {
"color": "#007bff",
"font-size": "18px"
},
"nav-link": {
"font-size": "14px",
"text-align": "center",
"margin": "5px",
"padding": "10px",
"--hover-color": "#e6e6e9",
"color": "#333333",
"border-radius": "10px",
"transition": "all 0.3s ease",
},
"nav-link-selected": {
"background-color":
"#ffffff",
"box-shadow":
"inset 3px 3px 5px #d1d1d4, inset -3px -3px 5px #ffffff"
},
"separator": {
"border-color": "#e0e0e3"
},
},
)
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": "#f0f0f3",
"border-radius": "15px",
"box-shadow":
"5px 5px 10px #d1d1d4, -5px -5px 10px #ffffff"
},
"icon": {
"color": "#007bff",
"font-size": "18px"
},
"nav-link": {
"font-size": "14px",
"text-align": "center",
"margin": "5px",
"padding": "10px",
"--hover-color": "#e6e6e9",
"color": "#333333",
"border-radius": "10px",
"transition": "all 0.3s ease",
},
"nav-link-selected": {
"background-color":
"#ffffff",
"box-shadow":
"inset 3px 3px 5px #d1d1d4, inset -3px -3px 5px #ffffff"
},
"separator": {
"border-color": "#e0e0e3"
},
},
)
dados_processados = processar_dados(raw_red, intervalo)
# Criação do gráfico
fig = go.Figure()
metricas = ["Usuários", "Domicílios", "Famílias"
] if metrica == "Todos" else [metrica]
cores = {
"Usuários": "#007bff",
"Domicílios": "#28a745",
"Famílias": "#ffc107"
}
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={
"color": cores[m],
"width": 3
},
marker={
"size": 12,
"symbol": "circle",
"line": {
"width": 2,
"color": "white"
}
},
))
fig.update_layout(
hoverlabel={
"bgcolor": "white",
"font_size": 16,
"font_family": "Arial",
},
hovermode="x unified",
)
fig.update_traces(hovertemplate="%{y}
%{x}")
st.plotly_chart(fig, use_container_width=True)
add_vertical_space(10)
st.write('----')