Diseño Experimental 2026-2 y Procesos 3 · Oct 7, 2026 · @Justo
Cada grupo va a comparar 4 secadores eléctricos con un Diseño Completamente al Azar (DCA) y a construir, en GitHub Codespaces, una app de Streamlit que aleatoriza el experimento, recibe los datos, dibuja las curvas de secado y hace el ANOVA. Es una actividad conjunta con Procesos 3 (profesor Alfredo Fernández).
Todo se hace sin laboratorio: solo se necesita una balanza, un termómetro o termocupla y un cronómetro. Todo el software es gratuito.
Al final, cada grupo entrega:
data/.La pregunta es: ¿los 4 secadores secan igual de rápido el mismo producto? Como los equipos son eléctricos y tienen temperatura controlada, las condiciones entre corridas son bastante homogéneas, y por eso un DCA es razonable. Con secadores solares, el clima de cada día obligaría a bloquear.
| Elemento | Definición en este experimento |
|---|---|
| Factor (tratamientos) | Secador, con 4 niveles: A, B, C y D |
| Unidad experimental | Una corrida: un lote de producto secado una vez en un secador |
| Réplicas | r = 4 corridas por secador (mínimo 3), en total N = 16 corridas |
| Aleatorización | El orden de las 16 corridas se sortea con la app |
| Respuesta principal | Pérdida de masa (%) a un tiempo fijo, por ejemplo 120 min |
| Respuesta secundaria | Constante de secado k del modelo exponencial |
| Variable de control | Temperatura media en el hogar durante la corrida |
Con r = 4, el error tiene 4 × (4 − 1) = 12 grados de libertad; con r = 3 tendría solo 8.
El modelo del DCA es:
\[y_{ij} = \mu + \tau_i + \varepsilon_{ij}, \qquad i = 1,\dots,4 \;\text{(secadores)}, \quad j = 1,\dots,r \;\text{(corridas)}\]
Sin estufa no se puede conocer la humedad exacta del producto, pero sí su pérdida de masa, que en el secado es casi toda agua:
\[PM_t(\%) = 100 \cdot \frac{m_0 - m_t}{m_0}\]
La curva de secado se describe con un modelo exponencial sobre la masa, donde mₑ es la masa a la que tiende el producto (masa de equilibrio) y k la constante de secado:
\[m_t = m_e + (m_0 - m_e)\, e^{-k t}\]
Un k mayor indica un secador que seca más rápido. La app estima mₑ y k para cada corrida, y después compara los k con el ANOVA.
Advertencia: si solo hay un equipo de cada tipo, las conclusiones son sobre esos 4 equipos concretos. Varias bandejas dentro de la misma corrida no son réplicas: la réplica es una corrida nueva.
En cada corrida se mide la masa de la bandeja y la temperatura en el hogar (donde están las muestras), siguiendo el calendario del profesor Fernández: el intervalo se duplica en cada tramo, porque al principio la masa cambia muy rápido.
| Tramo | Intervalo | Tiempos de lectura (min) |
|---|---|---|
| Inicio | — | 0 |
| Hasta 10 min | 1 min | 1, 2, 3, …, 10 |
| Hasta 20 min | 2 min | 12, 14, 16, 18, 20 |
| Hasta 40 min | 4 min | 24, 28, 32, 36, 40 |
| Hasta 80 min | 8 min | 48, 56, 64, 72, 80 |
| Hasta 160 min | 16 min | 96, 112, 128, 144, 160 |
| Hasta 320 min | 32 min | 192, 224, 256, 288, 320 |
La duración total se acuerda con el profesor Fernández antes del primer ensayo y es igual para todas las corridas. Si se fija en 240 min, la última lectura es 240.
Cómo medir:
Todas las corridas se guardan en un solo archivo CSV, en formato largo: una fila por lectura. La masa se anota sin la tara.
corrida,orden,secador,fecha,tiempo_min,masa_g,temp_hogar_C,temp_amb_C,observaciones
1,1,C,2026-10-14,0,200.4,24.8,29.5,
1,1,C,2026-10-14,1,199.1,38.2,29.5,
1,1,C,2026-10-14,2,197.6,45.0,29.6,puerta abierta 20 s
Al terminar, se empaca cada corrida en bolsas separadas, una por fecha: días 0, 4, 8, 12 y 15. En cada fecha se abre solo la bolsa que corresponde y se registra:
Textura, sólidos solubles, acidez y pH quedan pendientes mientras no haya laboratorio.
Un Codespace es un computador en la nube con VS Code, Python y Git ya instalados, que se abre en el navegador. Sirve aunque tu computador sea lento o no permita instalar programas.
secadores-dca-grupoN (N =
número del grupo). Marcar Public.Cada integrante trabaja en su propio Codespace, y las horas se descuentan de su propia cuenta. Si prefieres VS Code instalado, en el menú ☰ del Codespace elige Open in VS Code Desktop.
Esta parte la hace solo el líder, una vez. Los demás
la reciben con git pull (Parte 4).
En el explorador de la izquierda, crear el archivo
requirements.txt con este contenido:
streamlit
pandas
numpy
scipy
statsmodels
matplotlib
En la terminal del Codespace (si no está abierta: Ctrl+ñ
o menú ☰ → Terminal → New Terminal):
pip install -r requirements.txt
En el Codespace no hace falta entorno virtual: cada Codespace ya es un entorno aislado.
Crear la carpeta .devcontainer y dentro el archivo
devcontainer.json:
{
"image": "mcr.microsoft.com/devcontainers/python:3.12",
"postCreateCommand": "pip install -r requirements.txt",
"customizations": {
"vscode": {
"extensions": ["ms-python.python", "GitHub.copilot-chat"]
}
}
}
Así, cuando un compañero cree su Codespace, ya tendrá Python, las librerías y Copilot listos.
Crear app.py:
import streamlit as st
st.title("Secadores eléctricos – DCA")
st.write("Grupo N – Diseño Experimental y Procesos 3")
Ejecutar en la terminal:
streamlit run app.py --server.enableXsrfProtection false
Ctrl+C en la terminal.La opción --server.enableXsrfProtection false evita un
error frecuente en Codespaces al subir archivos CSV a la app.
La app tiene 4 páginas, y cada una se construye con un prompt. Abre
el chat de Copilot (Ctrl+Alt+I), elige el modo
Agent, pega el prompt y revisa cada cambio
antes de aceptarlo. Si se agota la cuota, pega el mismo prompt
en un chat gratuito (Claude, ChatGPT o Gemini) y copia el código a
mano.
Regla del curso: después de cada prompt, ejecuta la app, verifica un resultado a mano y anota en la bitácora qué pediste, qué salió y qué corregiste.
Actúa como tutor experto en Python, Streamlit y Diseño Experimental. Responde en español.
Estamos construyendo una app multipágina de Streamlit (app.py + carpeta pages/) para un
experimento con Diseño Completamente al Azar (DCA): 4 secadores eléctricos (A, B, C, D),
r = 4 corridas por secador, N = 16 corridas. En cada corrida se pesa la bandeja y se mide la
temperatura en el hogar en los tiempos 0, 1..10 (cada 1 min), 12..20 (cada 2), 24..40 (cada 4),
48..80 (cada 8), 96..160 (cada 16) y 192..320 (cada 32) minutos.
Los datos están en formato largo con columnas: corrida, orden, secador, fecha, tiempo_min,
masa_g, temp_hogar_C, temp_amb_C, observaciones.
Usa pandas, numpy, scipy, statsmodels y matplotlib. Código comentado, funciones reutilizables
en utils/ y nada de librerías que no estén en requirements.txt.
Crea pages/1_Aleatorizacion.py. Debe:
1. Pedir el número de réplicas r (por defecto 4) y una semilla (por defecto 2026).
2. Generar las 4*r corridas (secadores A, B, C, D, cada uno r veces) en orden aleatorio
usando numpy.random.default_rng(semilla), y mostrar la tabla corrida-orden-secador.
3. Permitir descargar esa tabla como CSV.
4. Generar y permitir descargar la plantilla de registro vacía en formato largo:
una fila por corrida y por cada tiempo del calendario, con masa_g y temperaturas vacías.
5. Explicar en un st.info por qué se aleatoriza el orden de las corridas en un DCA.
Crea utils/datos.py y pages/2_Datos.py. Debe:
1. Permitir subir el CSV de registro con st.file_uploader.
2. Si no se sube nada, usar datos simulados realistas generados con la función
simular_datos() de utils/datos.py, con el modelo m_t = m_e + (m0 - m_e)*exp(-k*t),
m0 cerca de 200 g, m_e cerca de 40 g, k distinto por secador y ruido de ±0.5 g.
3. Validar: columnas obligatorias, masa numérica, 4 secadores, sin datos faltantes en masa.
Mostrar mensajes de error claros y pedagógicos.
4. Calcular la pérdida de masa PM_t(%) = 100*(m0 - m_t)/m0 para cada corrida.
5. Mostrar la tabla y un resumen por corrida: masa inicial, masa final, PM final y temperatura media.
6. Guardar los datos en st.session_state para las demás páginas.
Crea utils/modelos.py y pages/3_Curvas.py. Debe:
1. Graficar la masa (g) contra el tiempo (min) para cada corrida, con un color por secador.
2. Graficar también la temperatura en el hogar contra el tiempo.
3. Para cada corrida, ajustar m_t = m_e + (m0 - m_e)*exp(-k*t) con scipy.optimize.curve_fit,
con valores iniciales razonables y límites positivos para m_e y k.
4. Mostrar una tabla por corrida con: secador, m0, m_e, k (1/min), R2 y la pérdida de masa
a un tiempo t* elegido por el usuario (por defecto 120 min).
5. Mostrar la curva ajustada sobre los puntos para la corrida que el usuario elija.
6. Permitir descargar la tabla resumen como CSV y guardarla en st.session_state.
Crea utils/anova.py y pages/4_ANOVA_DCA.py. Usando la tabla resumen (una fila por corrida):
1. Permitir elegir la respuesta: k o pérdida de masa a t*.
2. Ajustar el DCA con statsmodels: ols('respuesta ~ C(secador)') y anova_lm(typ=2).
3. Mostrar la tabla ANOVA con fuente, gl, SC, CM, F y valor p, más el CV (%).
4. Mostrar medias por secador con su error estándar y un diagrama de cajas.
5. Supuestos: Shapiro-Wilk de los residuos, Levene entre secadores, gráfico de residuos
contra ajustados y QQ-plot, con interpretación en lenguaje sencillo.
6. Si p < 0.05, prueba de Tukey HSD entre secadores.
7. Una interpretación automática prudente, que recuerde que las conclusiones son sobre estos
4 equipos.
8. Un st.toggle que muestre el código equivalente en R: aov(respuesta ~ secador) y
agricolae::HSD.test.
Escribe el README.md del repositorio: objetivo del experimento, diseño (DCA, factor,
unidad experimental, réplicas, respuestas), protocolo de medición, cómo abrir el proyecto en
Codespaces y ejecutar la app, estructura de carpetas, integrantes del grupo y limitaciones.
La regla de oro para no pisarse el trabajo es que cada integrante trabaja en archivos distintos.
| Integrante | Responsable de | Archivos |
|---|---|---|
| 1 (líder) | Estructura, entorno y aleatorización | requirements.txt, .devcontainer/,
app.py, pages/1_Aleatorizacion.py |
| 2 | Datos y registro real | utils/datos.py, pages/2_Datos.py,
data/registro_secadores.csv |
| 3 | Curvas y modelo de secado | utils/modelos.py, pages/3_Curvas.py |
| Todos | ANOVA, README y bitácora | pages/4_ANOVA_DCA.py, README.md,
bitacora_IA.md (por turnos) |
Cada vez que trabajes, sigue este ciclo en la terminal del Codespace:
git pull # 1. traer lo que subieron los compañeros
# ... trabajar, ejecutar y verificar ...
git add . # 2. preparar los cambios
git commit -m "Agrega ajuste del modelo exponencial por corrida"
git push # 3. subir a GitHub
También puedes hacerlo con clics en el panel Control de
código fuente (Ctrl+Shift+G): +
para preparar, Confirmar para el commit y Sincronizar
cambios para subir y bajar.
Si git push es rechazado porque alguien subió cambios
antes, ejecuta git pull y luego git push otra
vez. Si aparece un conflicto en un archivo, no borres
nada: pídele a Copilot en modo Ask que te explique el conflicto, o
avísale al docente.
Los datos reales se suben a data/registro_secadores.csv.
En el Codespace basta con arrastrar el archivo desde tu computador a la
carpeta data/ del explorador y luego hacer commit.
Las horas de Codespaces se cuentan por núcleo: una máquina de 2 núcleos gasta 2 horas de cuota por cada hora encendida (GitHub Docs).
| Cuenta | Cuota mensual | Horas reales en máquina de 2 núcleos | Almacenamiento |
|---|---|---|---|
| GitHub Free | 120 horas-núcleo | 60 horas | 15 GB |
| GitHub Pro (Student Developer Pack) | 180 horas-núcleo | 90 horas | 20 GB |
Para que alcance todo el semestre:
git push.| Problema | Solución |
|---|---|
| Al subir el CSV a la app aparece un error 403 | Ejecutar Streamlit con
--server.enableXsrfProtection false (Parte 2.3) |
ModuleNotFoundError: No module named 'streamlit' |
Ejecutar pip install -r requirements.txt |
| La app no abre en el navegador | Pestaña Puertos → globo del puerto 8501 |
ModuleNotFoundError: No module named 'utils' |
Ejecutar streamlit run app.py desde la raíz del
proyecto y crear utils/__init__.py vacío |
| El Codespace se detuvo solo | Es normal tras un rato sin uso; se reabre desde Code → Codespaces sin perder archivos |
curve_fit no converge en una corrida |
Revisar que la masa esté sin tara y sin datos mal digitados, y pedir a Copilot mejores valores iniciales |
Cada grupo envía al docente el enlace a su repositorio. El repositorio debe contener todo lo siguiente.