import streamlit as st
import pandas as pd
import folium
from folium.plugins import MarkerCluster, Search
from streamlit_folium import st_folium
import html
import io
# --- Configuración ---
st.set_page_config(page_title="Puntajes SIMCE 2024 - Centros Escolares", page_icon=":school:", layout="wide")
st.title(":school: Puntajes SIMCE 2024 - 2do Medio")
st.markdown("Explora los puntajes SIMCE de los establecimientos educacionales en Chile (Datos del MINEDUC)")
# --- Diccionarios para mapear valores a descripciones ---
dependencia_map = {
1: 'Municipal Corporación',
2: 'Municipal DAEM',
3: 'Particular subvencionado',
4: 'Particular pagado',
5: 'Corporación de administración delegada',
6: 'Servicio Local de Educación'
}
socioecon_map = {
1: 'Bajo',
2: 'Medio Bajo',
3: 'Medio',
4: 'Medio Alto',
5: 'Alto'
}
rural_map = {
1: 'Urbano',
2: 'Rural'
}
# --- Cargar datos ---
@st.cache_data
def load_data():
df = pd.read_csv(
"data/simce.csv",
sep=";",
decimal=",",
encoding="ISO-8859-1",
header=0,
on_bad_lines="skip"
)
# Crear columnas con descripciones
df['dependencia_desc'] = df['dependencia'].map(dependencia_map)
df['grupo_socioecon_desc'] = df['grupo_socioecon'].map(socioecon_map)
df['es_rural_desc'] = df['es_rural'].map(rural_map)
return df
# Cargar datos
df = load_data()
# --- Filtros ---
st.subheader("Filtros de Búsqueda")
col1, col2, col3, col4 = st.columns(4)
regiones = ["(Todas)"] + sorted(df["nombre_region"].dropna().unique().tolist())
ruralidades = ["(Todas)"] + sorted(df["es_rural_desc"].dropna().unique().tolist())
dependencias = ["(Todas)"] + sorted(df["dependencia_desc"].dropna().unique().tolist())
socioecons = ["(Todas)"] + sorted(df["grupo_socioecon_desc"].dropna().unique().tolist())
with col1:
sel_region = st.selectbox("Región", regiones, index=0, help="Selecciona una región para filtrar los establecimientos.")
with col2:
sel_ruralidad = st.selectbox("Ruralidad", ruralidades, index=0, help="Filtra por tipo de área (urbana o rural).")
with col3:
sel_dependencia = st.selectbox("Dependencia", dependencias, index=0, help="Filtra por tipo de establecimiento.")
with col4:
sel_socioecon = st.selectbox("Grupo Socioeconómico", socioecons, index=0, help="Filtra por nivel socioeconómico.")
# Filtrar datos
df_f = df.copy()
if sel_region != "(Todas)":
df_f = df_f[df_f["nombre_region"] == sel_region]
if sel_ruralidad != "(Todas)":
df_f = df_f[df_f["es_rural_desc"] == sel_ruralidad]
if sel_dependencia != "(Todas)":
df_f = df_f[df_f["dependencia_desc"] == sel_dependencia]
if sel_socioecon != "(Todas)":
df_f = df_f[df_f["grupo_socioecon_desc"] == sel_socioecon]
# Filtrar filas con coordenadas válidas
df_map = df_f.dropna(subset=["latitud", "longitud"])
# --- Estadísticas resumidas ---
st.subheader("Estadísticas Resumidas")
if not df_map.empty:
col_stats1, col_stats2 = st.columns(2)
with col_stats1:
st.metric("Número de Establecimientos", len(df_map))
st.metric("Promedio Lenguaje", f"{df_map['promedio_lectura'].mean():.1f}")
with col_stats2:
st.metric("Promedio Matemáticas", f"{df_map['promedio_matematica'].mean():.1f}")
st.metric("Regiones Cubiertas", df_map["nombre_region"].nunique())
else:
st.warning("No hay datos disponibles con los filtros seleccionados.")
# --- Mapeo de colores por tipo ---
color_map = {
'Municipal Corporación': 'blue',
'Municipal DAEM': 'green',
'Particular subvencionado': 'orange',
'Particular pagado': 'purple',
'Corporación de administración delegada': 'red',
'Servicio Local de Educación': 'cadetblue'
}
# Función para asignar color según tipo
def tipo_color(tipo: str) -> str:
return color_map.get(tipo, "gray")
# --- Crear mapa centrado en Chile ---
m = folium.Map(location=[-33.45, -70.65], zoom_start=6, tiles="CartoDB positron")
# Cluster
cluster = MarkerCluster().add_to(m)
# --- Agregar búsqueda por nombre de colegio ---
school_search = Search(
layer=cluster,
search_label="nombre_colegio",
placeholder="Buscar por nombre del colegio...",
collapsed=False,
).add_to(m)
# --- Agregar marcadores ---
for _, r in df_map.iterrows():
lat, lon = float(r["latitud"]), float(r["longitud"])
nombre = html.escape(str(r.get("nombre_colegio", "")))
comuna = html.escape(str(r.get("nombre_comuna", "")))
tipo = html.escape(str(r.get("dependencia_desc", "")))
lenguaje = html.escape(str(r.get("promedio_lectura", "")))
matematica = html.escape(str(r.get("promedio_matematica", "")))
rural = html.escape(str(r.get("es_rural_desc", "")))
grupoeconomico = html.escape(str(r.get("grupo_socioecon_desc", "")))
popup_html = f"""
{nombre}
Tipo: {tipo}
Comuna: {comuna}
Promedio Lenguaje: {lenguaje}
Promedio Matemáticas: {matematica}
Es Rural: {rural}
Grupo Socioeconómico: {grupoeconomico}
"""
marker = folium.Marker(
location=[lat, lon],
popup=folium.Popup(popup_html, max_width=350),
icon=folium.Icon(color=tipo_color(r.get("dependencia_desc")), icon="plus", prefix="fa"),
)
marker.add_to(cluster)
marker.properties = {"nombre_colegio": nombre} # Para búsqueda
# --- Leyenda mejorada ---
legend_html = """