Varcthor's picture
Upload 11 files
290c3fd verified
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"""
<b>{nombre}</b><br>
<b>Tipo:</b> {tipo}<br>
<b>Comuna:</b> {comuna}<br>
<b>Promedio Lenguaje:</b> {lenguaje}<br>
<b>Promedio Matem谩ticas:</b> {matematica}<br>
<b>Es Rural:</b> {rural}<br>
<b>Grupo Socioecon贸mico:</b> {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 = """
<div style="
position: fixed;
bottom: 30px; left: 30px; z-index: 9999;
background: white; padding: 12px; border: 2px solid #ccc; border-radius: 10px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1); font-family: Arial, sans-serif; font-size: 14px;">
<b style="color:black; font-size: 16px;">Leyenda</b><br>
<span style="display:inline-block;width:14px;height:14px;border-radius:50%;background:blue;margin-right:8px;"></span><span style="color:black;">Municipal Corporaci贸n</span><br>
<span style="display:inline-block;width:14px;height:14px;border-radius:50%;background:green;margin-right:8px;"></span><span style="color:black;">Municipal DAEM</span><br>
<span style="display:inline-block;width:14px;height:14px;border-radius:50%;background:orange;margin-right:8px;"></span><span style="color:black;">Particular subvencionado</span><br>
<span style="display:inline-block;width:14px;height:14px;border-radius:50%;background:purple;margin-right:8px;"></span><span style="color:black;">Particular pagado</span><br>
<span style="display:inline-block;width:14px;height:14px;border-radius:50%;background:red;margin-right:8px;"></span><span style="color:black;">Corporaci贸n de administraci贸n delegada</span><br>
<span style="display:inline-block;width:14px;height:14px;border-radius:50%;background:cadetblue;margin-right:8px;"></span><span style="color:black;">Servicio Local de Educaci贸n</span><br>
<span style="display:inline-block;width:14px;height:14px;border-radius:50%;background:gray;margin-right:8px;"></span><span style="color:black;">Otros</span>
</div>
"""
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",
)