El objetivo es el mismo: que cualquiera abra tu trabajo desde un navegador, sin instalar nada. Cambia quién ejecuta el código, y de ahí se derivan todas las demás diferencias.
Ruta A · Streamlit
Tu Python se sigue ejecutando, pero en un servidor. El navegador solo muestra el resultado.
Ruta B · HTML + JS
No hay Python. El navegador ejecuta JavaScript sobre datos que exportaste antes.
Cinco pasos desde el script que ya tienes hasta un enlace que puedes mandar por WhatsApp. Las siguientes diapositivas desarrollan cada uno.
streamlit run app.py abre el navegador en tu máquinarequirements.txt con las libreríasLas dos gratuitas, y la de Streamlit se crea con la de GitHub.
Un enlace público y permanente. Cada vez que hagas push, la app se actualiza sola.
La primera vez. Las siguientes, el despliegue es automático.
Aquí Python solo aparece al principio, para preparar los datos. Lo que se publica son archivos que el navegador entiende directamente.
.json ligeroindex.html, style.css y app.jsindex.html con doble clicSolo una. No hace falta ningún servicio adicional.
Un sitio estático. Carga al instante y no caduca.
No vas a aprender JavaScript en este curso: se lo pides al agente y tú revisas que haga lo correcto.
Streamlit no te obliga a reescribir nada. Tomas el script que ya tienes y le añades líneas st. donde quieras que aparezca algo en pantalla.
1 Lo que ya tenías
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("datos/ventas_empresa.csv")
g = (df.groupby("categoria_producto")["ventas_cop"]
.sum().sort_values() / 1e6)
fig, ax = plt.subplots()
ax.barh(g.index, g.values)
plt.show()
2 Lo mismo, como app
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
st.title("Panel de ventas 2025")
df = pd.read_csv("datos/ventas_empresa.csv")
# un filtro: el usuario elige la ciudad
ciudad = st.selectbox("Ciudad",
df["ciudad"].unique())
df = df[df["ciudad"] == ciudad]
st.metric("Ventas totales",
f"${df['ventas_cop'].sum():,.0f}")
g = (df.groupby("categoria_producto")["ventas_cop"]
.sum().sort_values() / 1e6)
fig, ax = plt.subplots()
ax.barh(g.index, g.values)
st.pyplot(fig) # en vez de plt.show()
st.dataframe(df) # la tabla, interactiva
Nunca despliegues algo que no has visto funcionar. Streamlit levanta un servidor en tu propia máquina y abre el navegador solo.
pip install streamlit streamlit run app.py
You can now view your Streamlit app in your browser. Local URL: http://localhost:8501 Network URL: http://192.168.1.14:8501
app.py, el navegador te ofrece recargar.
Las rutas cambian al desplegar
"datos/ventas.csv" funciona en tu máquina y también en el servidor solo si subes la carpeta datos al repositorio. Es el fallo número uno del primer despliegue.
Lo que falla en local va a fallar igual en internet, pero allí es mucho más difícil de diagnosticar.
Streamlit Cloud no lee tu computador: lee un repositorio. Necesita el código, los datos y la lista de librerías.
1 Qué tiene que haber en el repositorio
mi-panel-ventas/ ├── app.py # la aplicación ├── requirements.txt # las librerías └── datos/ └── ventas_empresa.csv # los datos
streamlit pandas matplotlib seaborn
2 Subirlo
git init git add . git commit -m "Panel de ventas" git branch -M main git remote add origin https://github.com/TU_USUARIO/mi-panel-ventas.git git push -u origin main
requirements.txt no es opcional. Sin él, el servidor no sabe que necesita pandas y la app falla al arrancar con ModuleNotFoundError — el mismo error del Módulo 1.
Es el paso más corto: conectas la cuenta de GitHub, señalas el repositorio y esperas un par de minutos.
1 · Entra en share.streamlit.io con tu cuenta de GitHub
2 · New app
3 · Elige el repositorio, la rama main y el archivo app.py
4 · Deploy
mi-panel-ventas.streamlit.app. Ese enlace ya se puede compartir con quien sea.
git push actualiza la app sola. No hay que volver a desplegar.
! Si tu app usa credenciales
[gcp_service_account] type = "service_account" project_id = "mi-proyecto" private_key = "-----BEGIN PRIVATE KEY-----\n..." client_email = "app@mi-proyecto.iam.gserviceaccount.com"
# en tu computador: desde un archivo local # en el servidor: desde los Secrets try: creds = Credentials.from_service_account_file( "credentials.json", scopes=SCOPES) except FileNotFoundError: creds = Credentials.from_service_account_info( st.secrets["gcp_service_account"], scopes=SCOPES)
Así el mismo código funciona en local y desplegado, sin que la clave llegue nunca al repositorio.
Un navegador solo entiende tres cosas: HTML, CSS y JavaScript. No hay Python. Por eso, para publicar sin servidor, hay que traducir.
Qué elementos hay: títulos, un menú desplegable, el hueco de la gráfica, la tabla.
Colores, tamaños, espaciados. Es lo mismo que hace el diseño de estas diapositivas.
Lo que pandas hacía: filtrar, agrupar, sumar. Y dibujar la gráfica cuando cambia el filtro.
No vas a escribirlo tú
Le pasas al agente tu script de Python y le dices: "conviérteme esto en una página con HTML, CSS y JavaScript, sin librerías externas". Tu trabajo es revisar que los números coincidan con los de tu análisis.
Lo que se pierde
scikit-learn, statsmodels y cualquier cálculo pesado no existen en el navegador. Si tu app necesita entrenar un modelo, esta ruta no sirve: usa la A.
JavaScript no puede abrir tu Excel. El puente es JSON: un formato de texto que el navegador lee de forma nativa, y que pandas exporta en una línea.
1 Exportar desde Python
import pandas as pd
from pathlib import Path
df = pd.read_csv("datos/ventas_empresa.csv")
# solo las columnas que la página va a usar
df = df[["fecha", "ciudad", "categoria_producto",
"unidades", "ventas_cop"]]
df.to_json("datos.json", orient="records",
force_ascii=False)
force_ascii=False conserva las tildes. Sin él, Bogotá se convierte en Bogot\u00e1.
2 Cómo queda el archivo
[
{"fecha": "2025-01-06", "ciudad": "Armenia",
"categoria_producto": "Papelería y consumibles",
"unidades": 9, "ventas_cop": 157460},
{"fecha": "2025-01-07", "ciudad": "Envigado",
"categoria_producto": "Muebles y oficina",
"unidades": 5, "ventas_cop": 2101320}
]
Con los datos ya en JSON, la página es un esqueleto que los lee y los pinta. Así se ve la estructura mínima.
mi-panel/ ├── index.html ├── style.css ├── app.js └── datos.json
<!DOCTYPE html> <html lang="es"> <head> <meta charset="utf-8"> <title>Panel de ventas</title> <link rel="stylesheet" href="style.css"> </head> <body> <h1>Panel de ventas 2025</h1> <select id="ciudad"></select> <p id="total"></p> <canvas id="grafica"></canvas> <script src="app.js"></script> </body> </html>
// cargar el JSON const datos = await fetch("datos.json") .then(r => r.json()); // filtrar -> df[df.ciudad == x] const filtrados = datos.filter( d => d.ciudad === ciudadElegida); // sumar -> df["ventas_cop"].sum() const total = filtrados.reduce( (a, d) => a + d.ventas_cop, 0); document.getElementById("total").textContent = "Ventas: $" + total.toLocaleString("es-CO");
.filter() es el df[df.col == x] de pandas y .reduce() es el .sum(). Cambia la sintaxis, no la idea.
GitHub puede servir cualquier repositorio como si fuera un sitio web. Es un interruptor, y es gratis para siempre.
git init git add . git commit -m "Panel de ventas" git branch -M main git remote add origin https://github.com/TU_USUARIO/mi-panel.git git push -u origin main
1 · En el repositorio, pestaña Settings
2 · Menú lateral, Pages
3 · En Source, elige la rama main y la carpeta / (root)
4 · Save
Tu dirección
En un par de minutos estará en:
https://TU_USUARIO.github.io/mi-panel/
El archivo se debe llamar index.html
Si lo llamas panel.html, la dirección raíz dará error 404. GitHub Pages busca index.html por convención.
datos.json. No publiques datos personales ni confidenciales.
No hay una mejor: hay una adecuada para cada caso. Estas cinco preguntas resuelven casi siempre la duda.
Elige Streamlit si…
Elige GitHub Pages si…
En la práctica mucha gente hace las dos: el panel interactivo en Streamlit para trabajar, y una versión estática en GitHub Pages como carta de presentación.
Empezaste sin saber qué era una variable. Ahora cargas datos reales, los analizas, los grafícas y los publicas en internet para que cualquiera los use.
Módulo 1
fundamentos de Python y agentes de IA
Módulo 2
cargar, limpiar y exportar datos
Módulo 3
gráficas que se entienden
Módulo 4
tu aplicativo publicado
Trabajo Científico · @TCientifico · Democratizando la ciencia de datos