Widgets, Sidebar y Navegación
2026-04-15
Widgets · Sidebar · Navegación
✅ Sidebar con menú · ✅ Dataset real de Kaggle · ✅ Tabla interactiva · ✅ Gráfico Plotly
Regla de oro: controles, filtros y configuración → sidebar · tablas, gráficos y resultados → centro
st.sidebar.title("Configuración")
st.sidebar.slider("Año", 2018, 2024)
st.sidebar.selectbox("País", ["USA","China"])
st.sidebar.button("Aplicar")
with ✅with st.sidebar:
st.title("Configuración")
st.slider("Año", 2018, 2024)
st.selectbox("País", ["USA","China"])
st.button("Aplicar")
Las dos formas hacen exactamente lo mismo. La mayoría prefiere with st.sidebar: cuando hay más de 3 widgets porque es más fácil de leer.
st.selectbox() — Lista desplegableopcion = st.selectbox(
label="¿Qué quieres ver?",
options=["Datos", "Gráfico", "Resumen"],
index=0, # cuál empieza seleccionado
key="menu", # ID único (importante si hay varios)
help="Elige la vista" # tooltip con ?
)
# La variable guarda el texto elegido:
st.write(f"Elegiste: {opcion}")
st.radio() — Botones de opción visiblespagina = st.radio(
label="Navegar a:",
options=["📊 Ver Datos", "📈 Ver Gráfico"],
index=0, # opción inicial
horizontal=False, # True = en fila horizontal
key="navegacion"
)
if pagina == "📊 Ver Datos":
st.write("Mostrando la tabla...")
elif pagina == "📈 Ver Gráfico":
st.write("Mostrando el gráfico...")
| selectbox 📋 | radio 📻 | |
|---|---|---|
| Opciones visibles | Solo la elegida | Todas siempre |
| Cantidad ideal | 5 o más ✅ | 2 a 4 ✅ |
| Espacio que ocupa | Muy poco | Más espacio |
| Úsalo para... | Países, años, categorías largas | Menú de páginas 👈 |
Para el menú de navegación → usaremos st.radio en el sidebar. Pocas opciones, siempre visibles.
¿Por qué este dataset? Tiene texto (países), números (aranceles) y fechas → perfecto para filtros, tablas y gráficos.
⏸ Pausa — descarga el CSV ahora. Los que ya lo tienen esperan 2 minutos.
st.file_uploader() — el usuario sube el archivoarchivo = st.file_uploader(
label="Sube el CSV de Kaggle",
type=["csv"], # solo acepta CSV
key="uploader",
help="Descárgalo de Kaggle primero"
)
# ⚠️ SIEMPRE verificar antes de usar
if archivo is not None:
df = pd.read_csv(archivo)
st.success("¡Archivo cargado! ✅")
st.write(df)
else:
st.info("Sube un archivo para comenzar")
if archivo is not None:import pandas as pd # una vez, arriba del todo
if archivo is not None:
df = pd.read_csv(archivo) # CSV → tabla en memoria
# Métricas rápidas
col1, col2, col3 = st.columns(3)
col1.metric("Filas", len(df))
col2.metric("Países únicos", df["country"].nunique())
col3.metric("Arancel máx", f"{df['tariff_rate_pct'].max():.1f}%")
st.divider()
# Tabla interactiva — el usuario puede ordenar y buscar
st.dataframe(
df,
use_container_width=True,
height=300,
hide_index=True
)
st.radio con los nombres de las páginas
pagina
if / elif decide qué contenido mostrar en el centro
No hay magia. Es Python normal. Cuando el usuario cambia el radio → el script corre de nuevo → el if decide qué página mostrar.
with st.sidebar:
st.title("🗂️ Navegación")
pagina = st.radio("Ir a:", ["📊 Ver Datos", "📈 Ver Gráfico"])
if pagina == "📊 Ver Datos":
st.title("Tabla de Aranceles")
st.dataframe(df)
elif pagina == "📈 Ver Gráfico":
st.title("Gráfico de Aranceles")
st.plotly_chart(fig)
pip install plotly — una vez, luego ya está disponible en todos tus proyectos.
import plotly.express as px # siempre así, arriba
# Datos de ejemplo
datos = {
"País": ["China", "Mexico", "Canada", "EU"],
"Arancel": [25, 15, 7, 20]
}
df_ej = pd.DataFrame(datos)
# Crear el gráfico — 1 línea ✨
fig = px.bar(
df_ej,
x="País", # columna para el eje X
y="Arancel", # columna para el eje Y
title="Aranceles por País",
color="Arancel",
color_continuous_scale="Reds"
)
st.plotly_chart(fig, use_container_width=True)
import plotly.express as pxpx.bar(df, x="...", y="...")st.plotly_chart(fig)with st.sidebar:
pagina = st.radio("Ir a:",
["Datos", "Gráfico"])
if pagina == "Datos":
st.dataframe(df)
elif pagina == "Gráfico":
st.plotly_chart(fig)
mi-proyecto/
app.py ← portada
pages/
1_Datos.py ← página 1
2_Grafico.py ← página 2
3_Filtros.py ← página 3
pages/Streamlit detecta automáticamente la carpeta pages/ y crea el menú lateral. Sin código extra de navegación.
pages/ y el menú automático1_, 2_, 3_ controlan el orden. El guion bajo se convierte en espacio en el menú.# app.py — portada
import streamlit as st
# ⚠️ DEBE ser el PRIMER comando de Streamlit en el archivo
st.set_page_config(
page_title="Dashboard Aranceles",
page_icon="🇺🇸",
layout="wide"
)
st.title("🇺🇸 Dashboard — Aranceles USA")
st.write("Bienvenido. Usa el menú lateral para navegar.")
st.info("👈 Selecciona una página en el menú de la izquierda")
# pages/1_Datos.py
import streamlit as st
import pandas as pd
st.title("📊 Tabla de Aranceles")
archivo = st.sidebar.file_uploader("Sube el CSV", type=["csv"])
if archivo is None:
st.info("Sube el archivo CSV desde el panel lateral.")
st.stop() # ← para aquí si no hay archivo
df = pd.read_csv(archivo)
col1, col2, col3 = st.columns(3)
col1.metric("Filas", len(df))
col2.metric("Países", df["country"].nunique())
col3.metric("Máx %", f"{df['tariff_rate_pct'].max():.1f}%")
st.dataframe(df, use_container_width=True, height=320)
# pages/2_Grafico.py
import streamlit as st
import pandas as pd
import plotly.express as px
st.title("📈 Gráfico de Aranceles")
archivo = st.sidebar.file_uploader("Sube el CSV", type=["csv"])
if archivo is None:
st.info("Sube el archivo CSV desde el panel lateral.")
st.stop() # ← para aquí si no hay archivo
df = pd.read_csv(archivo)
resumen = df.groupby("country")["tariff_rate_pct"].mean().reset_index()
fig = px.bar(resumen.sort_values("tariff_rate_pct"),
x="tariff_rate_pct", y="country", orientation="h",
title="Arancel promedio por país",
color="tariff_rate_pct", color_continuous_scale="Reds",
labels={"tariff_rate_pct": "Arancel (%)", "country": "País"})
st.plotly_chart(fig, use_container_width=True)
st.stop() y st.set_page_config()archivo = st.file_uploader("CSV")
# archivo es None al arrancar
df = pd.read_csv(archivo)
# ↑ ERROR: no se puede leer None
st.dataframe(df)
archivo = st.file_uploader("CSV")
if archivo is None:
st.info("Sube un archivo 👆")
st.stop() # ← para aquí
# Solo llega aquí si hay archivo
df = pd.read_csv(archivo) # seguro ✅
st.dataframe(df)
Regla: siempre que dependas de algo que el usuario aún no hizo → st.stop() antes de usarlo. Y set_page_config() siempre va primero en el archivo.
with st.sidebar: para organizar controles!= Nonepx.bar() + st.plotly_chart()¡A construir! 🗂️
Módulo 2 — Completado
Preguntas antes de cerrar 🙋
Módulo 2 · Streamlit · Sidebar y Navegación