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 = """
Leyenda
Municipal Corporación
Municipal DAEM
Particular subvencionado
Particular pagado
Corporación de administración delegada
Servicio Local de Educación
Otros
""" m.get_root().html.add_child(folium.Element(legend_html)) # --- Botón para reiniciar mapa --- if st.button("Reiniciar Mapa"): m = folium.Map(location=[-33.45, -70.65], zoom_start=6, tiles="CartoDB positron") st.experimental_rerun() # --- Mostrar el mapa --- st_folium(m, width=1200, height=650) # --- Vista de tabla y exportación --- with st.expander("Ver tabla filtrada"): columns_to_display = ['nombre_region', 'nombre_comuna', 'nombre_colegio', 'dependencia_desc', 'grupo_socioecon_desc', 'es_rural_desc', 'promedio_lectura', 'promedio_matematica'] st.dataframe(df_map[columns_to_display]) # Exportar datos filtrados csv = df_map[columns_to_display].to_csv(index=False) st.download_button( label="Descargar datos filtrados como CSV", data=csv, file_name="simce_filtrado.csv", mime="text/csv", )