Spaces:
Running
Running
import pandas as pd | |
import plotly.express as px | |
import streamlit as st | |
from pathlib import Path | |
from streamlit_extras.add_vertical_space import add_vertical_space | |
from streamlit_extras.stylable_container import stylable_container | |
st.title("Atualização de cadastro - UBS Flamengo") | |
add_vertical_space(10) | |
uploaded_file = st.sidebar.file_uploader("Adicione o arquivo Excel", type=".xlsx") | |
if uploaded_file is not None: | |
# Função para carregar e processar os dados | |
def load_data(file): | |
df = pd.read_excel(file, sheet_name="ANALISE", engine='openpyxl') | |
df["ATUALIZADO"] = pd.to_datetime(df["ATUALIZADO"], errors="coerce", dayfirst=True) | |
df["Trimestre"] = df["ATUALIZADO"].dt.to_period("Q") | |
df["Mês"] = df["ATUALIZADO"].dt.to_period("M") | |
df["Semestre"] = df["ATUALIZADO"].dt.to_period("6M") | |
df["RUA"] = df["RUA"].astype(str) | |
return df | |
df = load_data(uploaded_file) | |
# CSS customizado para o tema escuro | |
st.markdown( | |
""" | |
<style> | |
.reportview-container { | |
background: #0e1117; | |
color: #fafafa; | |
} | |
.big-font { | |
font-size:30px !important; | |
font-weight: bold; | |
color: #fafafa; | |
} | |
.stSelectbox [data-baseweb="select"] { | |
background-color: #262730; | |
} | |
.stSelectbox [data-baseweb="select"] > div { | |
background-color: #262730; | |
color: #fafafa; | |
} | |
</style> | |
""", | |
unsafe_allow_html=True, | |
) | |
# Seleção de Rua, Ano e Granularidade | |
col1, col2, col3, col4 = st.columns([1, 1, 1, 3]) | |
with col1: | |
rua_selecionada = st.selectbox("Selecione a Rua", sorted(df["RUA"].unique())) | |
with col2: | |
anos_disponiveis = sorted(df["ATUALIZADO"].dt.year.dropna().unique(), reverse=True) | |
anos_disponiveis.insert(0, "Total") | |
ano_selecionado = st.selectbox("Selecione o Ano", anos_disponiveis) | |
with col3: | |
granularidade = st.selectbox( | |
"Selecione a Granularidade", ["Mensal", "Trimestral", "Semestral"] | |
) | |
with col4: | |
st.write('') | |
# Filtragem de dados | |
if ano_selecionado == "Total": | |
dados_filtrados = df[df["RUA"] == rua_selecionada] | |
else: | |
dados_filtrados = df[ | |
(df["RUA"] == rua_selecionada) & (df["ATUALIZADO"].dt.year == ano_selecionado) | |
] | |
# Adicionar coluna de período baseado na granularidade | |
if granularidade == "Mensal": | |
dados_filtrados["Período"] = dados_filtrados["ATUALIZADO"].dt.strftime("%m-%Y") | |
elif granularidade == "Trimestral": | |
dados_filtrados["Período"] = ( | |
dados_filtrados["ATUALIZADO"].dt.to_period("Q").astype(str) | |
) | |
else: # Semestral | |
dados_filtrados["Período"] = ( | |
dados_filtrados["ATUALIZADO"].dt.to_period("6M").astype(str) | |
) | |
# Função para criar scatter plot | |
def create_scatter_plot(data, title): | |
fig = px.scatter( | |
data, | |
x="ATUALIZADO", | |
y="IDADE", | |
color="Período", | |
hover_data=["NOME", "ATUALIZADO", "Período"], | |
title=title, | |
color_discrete_sequence=px.colors.qualitative.Set3, | |
) | |
fig.update_layout( | |
xaxis_title="Período", | |
yaxis_title="Idade", | |
legend_title="Período", | |
plot_bgcolor="#0e1117", | |
paper_bgcolor="#0e1117", | |
font=dict(color="#fafafa"), | |
) | |
fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='#31333F', tickangle=45) | |
fig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='#31333F') | |
return fig | |
# Scatter plot principal | |
st.subheader( | |
f"Última Atualização na Rua {rua_selecionada} ({granularidade} - {ano_selecionado})" | |
) | |
c1, c2 = st.columns([0.8, 0.2]) | |
with c1: | |
fig = create_scatter_plot(dados_filtrados, f"Pacientes Pendentes de Atualização - {rua_selecionada}") | |
st.plotly_chart(fig, use_container_width=True) | |
with c2: | |
total_usuarios = len(dados_filtrados) | |
st.dataframe(dados_filtrados[["NOME", "IDADE", "RUA", "NUM", "Período"]].sort_values(by="Período", ascending=True), hide_index=True) | |
st.write(f"Total de usuários: {total_usuarios}") | |
add_vertical_space() | |
st.write('-----') | |
add_vertical_space() | |
c3, c4, c5 = st.columns([2, 2, 1]) | |
with c3: | |
st.markdown('') | |
with c4: | |
st.subheader("Análise por Faixa Etária") | |
with c5: | |
st.markdown('') | |
co1, co2, co3 = st.columns([2, 2, 2]) | |
with co1: | |
with stylable_container( | |
key="pueri", | |
css_styles=""" | |
img { | |
width: 460px; | |
height: 180px; | |
overflow: hidden; | |
position: relative; | |
object-fit: cover; | |
border-radius: 14px; /* 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("pueri.jpg") | |
with co2: | |
with stylable_container( | |
key="prev", | |
css_styles=""" | |
img { | |
width: 460px; | |
height: 180px; | |
overflow: hidden; | |
position: relative; | |
object-fit: cover; | |
border-radius: 14px; /* 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("prev.jpg") | |
with co3: | |
with stylable_container( | |
key="mamo", | |
css_styles=""" | |
img { | |
width: 460px; | |
height: 180px; | |
overflow: hidden; | |
position: relative; | |
object-fit: cover; | |
border-radius: 14px; /* 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("mamo.jpg") | |
# Preventivo (25-64 anos) | |
preventivo = dados_filtrados[ | |
(dados_filtrados["IDADE"].between(25, 64)) & (dados_filtrados["SEXO"] == "F") | |
] | |
st.markdown("### Preventivo (25-64 anos)") | |
fig_preventivo = create_scatter_plot(preventivo, f"Preventivo - {rua_selecionada}") | |
st.plotly_chart(fig_preventivo, use_container_width=True) | |
col1, col2 = st.columns([0.4, 0.6]) | |
with col1: | |
st.dataframe( | |
preventivo[["NOME", "RUA", "NUM", "ATUALIZADO", "IDADE", "Período"]].sort_values( | |
by="ATUALIZADO", ascending=False | |
), | |
hide_index=True, | |
) | |
with col2: | |
st.markdown(f"#### Total de usuários: {len(preventivo)}") | |
add_vertical_space() | |
# Mamografia (50-69 anos) | |
mamografia = dados_filtrados[ | |
(dados_filtrados["IDADE"].between(50, 69)) & (dados_filtrados["SEXO"] == "F") | |
] | |
st.markdown("### Mamografia (50-69 anos)") | |
fig_mamografia = create_scatter_plot(mamografia, f"Mamografia - {rua_selecionada}") | |
st.plotly_chart(fig_mamografia, use_container_width=True) | |
col1, col2 = st.columns([0.4, 0.6]) | |
with col1: | |
st.dataframe( | |
mamografia[["NOME", "RUA", "NUM", "ATUALIZADO", "IDADE", "Período"]].sort_values( | |
by="ATUALIZADO", ascending=False | |
), | |
hide_index=True, | |
) | |
with col2: | |
st.markdown(f"#### Total de usuários: {len(mamografia)}") | |
add_vertical_space() | |
st.write('-----') | |
add_vertical_space() | |
st.markdown("### Crianças 0 - 2 anos e 0 - 4 anos.") | |
# Crianças até 4 anos | |
criancasdois = dados_filtrados[dados_filtrados["IDADE"] <= 2] | |
criancasquatro = dados_filtrados[dados_filtrados["IDADE"] <= 4] | |
on = st.toggle("Alterne para ver as crianças até dois anos ou até 4 anos.") | |
if on: | |
st.markdown("### Crianças até 2 anos") | |
fig_criancasdois = create_scatter_plot(criancasdois, f"Crianças até 2 anos - {rua_selecionada}") | |
st.plotly_chart(fig_criancasdois, use_container_width=True) | |
col1, col2 = st.columns([0.4, 0.6]) | |
with col1: | |
st.dataframe( | |
criancasdois[["NOME", "RUA", "NUM", "ATUALIZADO", "IDADE", "Período"]].sort_values( | |
by="ATUALIZADO", ascending=False | |
), | |
hide_index=True, | |
) | |
with col2: | |
st.markdown(f"#### Total de usuários: {len(criancasdois)}") | |
else: | |
st.markdown("### Crianças até 4 anos") | |
fig_criancasquatro = create_scatter_plot(criancasquatro, f"Crianças até 4 anos - {rua_selecionada}") | |
st.plotly_chart(fig_criancasquatro, use_container_width=True) | |
col1, col2 = st.columns([0.4, 0.6]) | |
with col1: | |
st.dataframe( | |
criancasquatro[["NOME", "RUA", "NUM", "ATUALIZADO", "IDADE", "Período"]].sort_values( | |
by="ATUALIZADO", ascending=False | |
), | |
hide_index=True, | |
) | |
with col2: | |
st.markdown(f"#### Total de usuários: {len(criancasquatro)}") | |
st.write('-----------') | |
# Percentage of updates by period | |
st.subheader( | |
f"Porcentagem de Atualizações por {granularidade} na Rua {rua_selecionada}" | |
) | |
period_count = dados_filtrados["Período"].value_counts().sort_index() | |
period_percent = (period_count / len(dados_filtrados)) * 100 | |
period_data = pd.DataFrame( | |
{ | |
"Período": period_count.index, | |
"Porcentagem": period_percent.values.round(2), | |
"Atualizações": period_count.values, | |
} | |
) | |
st.dataframe(period_data, hide_index=True) | |
fig_period = px.bar( | |
period_data, | |
x="Período", | |
y="Porcentagem", | |
text="Atualizações", | |
title=f"Porcentagem de Atualizações por {granularidade}", | |
color="Porcentagem", | |
color_continuous_scale="Viridis", | |
) | |
fig_period.update_traces( | |
texttemplate="%{text}", | |
textposition="outside", | |
hovertemplate="%{x}: %{y:.2f}%<br>Atualizações: %{text}<extra></extra>", | |
) | |
fig_period.update_layout( | |
xaxis_title=granularidade, | |
yaxis_title="Porcentagem", | |
yaxis_tickformat=".2f", | |
plot_bgcolor="white", | |
) | |
fig_period.update_xaxes(showgrid=True, gridwidth=1, gridcolor="lightgray") | |
fig_period.update_yaxes(showgrid=True, gridwidth=1, gridcolor="lightgray") | |
st.plotly_chart(fig_period, use_container_width=True) | |
else: | |
st.markdown('# Insira o arquivo com os dados') | |