# metodos-de-econometria-aplicada-con-python
Métodos de Econometría Aplicada con Python
Volver a la portada del cursoEstructura de un Proyecto en Python
Sección 1 · Introducción a Econometría y Python
Estructura de un proyecto en Python
Un análisis econométrico vale lo que vale su reproducibilidad. Si dentro de seis meses alguien de Café Altura pregunta de dónde salió la elasticidad de −1.30, deberías poder volver a ejecutar todo y obtener la misma cifra. Eso no depende del modelo: depende de cómo organizas carpetas, datos, versiones y código. En esta lección armas la estructura que usarás durante el curso. Los datos de Café Altura son simulados, pero la estructura es la misma que usarías con datos reales.
1. Un árbol de carpetas que separa responsabilidades
La regla es simple: cada carpeta tiene un solo propósito y nadie edita a mano lo que produce el código.
cafe-altura/
├── data/
│ ├── raw/ # datos tal como llegaron (no se tocan)
│ └── processed/ # datos limpios generados por código
├── notebooks/ # exploración y explicación
├── src/
│ └── cafe_altura/
│ ├── __init__.py
│ └── datos.py # funciones reutilizables
├── reports/ # figuras e informes finales
├── pyproject.toml
├── .gitignore
└── README.md
data/rawguarda el extracto del punto de venta, el catálogo de tiendas o la descarga de INEGI tal como llegó. Es inmutable: si corriges algo, lo haces en código y escribes el resultado endata/processed.notebooks/sirve para explorar y contar la historia. Un notebook que define diez funciones y las usa en otros tres es una señal de que esas funciones pertenecen asrc/.src/contiene el código que se importa: generación o carga de datos, limpieza y funciones de estimación.reports/recibe las salidas: gráficas, tablas y el informe para la dirección.
2. Versiones fijas: el mismo resultado en otra máquina
Los resultados econométricos cambian entre versiones de las librerías: cambian valores por omisión, nombres de parámetros y hasta algoritmos de optimización. Por eso conviene declarar las dependencias con versiones mínimas en pyproject.toml, el archivo estándar de configuración de proyectos de Python:
[project]
name = "cafe-altura"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
"pandas>=2.2",
"statsmodels>=0.14",
"linearmodels>=6.0",
"matplotlib>=3.8",
]
Si prefieres algo más simple, un requirements.txt con pip freeze > requirements.txt fija las versiones exactas del entorno. Este curso se probó con statsmodels 0.14.6, linearmodels 7.1, pandas 3.0.3 y NumPy 2.4.6. Instala todo dentro de un entorno virtual (python -m venv .venv o uv venv) para no mezclar proyectos.
3. Funciones de datos en src/
Todo el curso usa las mismas funciones de Café Altura: generar_tiendas(), generar_ventas(), generar_panel(), generar_mensual() y generar_clientes(). En un proyecto real vivirían en src/cafe_altura/datos.py, con semilla fija para que cada ejecución produzca exactamente los mismos números:
import numpy as np
import pandas as pd
def generar_panel(semilla=42):
"""Ventas semanales unidas con el catálogo de tiendas."""
t = generar_tiendas(semilla)
df = generar_ventas(semilla).merge(t, on="tienda")
df["log_ventas"] = np.log(df["ventas"])
df["log_precio"] = np.log(df["precio"])
return df
El notebook solo importa y analiza. Con la semilla 42, generar_panel() devuelve siempre 4160 filas: 40 tiendas por 104 semanas. Si alguien obtiene otra forma, sabe de inmediato que algo cambió. En los notebooks del curso estas funciones se copian en la primera celda para que cada archivo sea autocontenido; en tu proyecto conviene importarlas.
4. Guardar resultados intermedios con rutas relativas a la raíz
Las rutas absolutas (C:\Users\...) rompen el proyecto en cualquier otra computadora. Usa pathlib y construye las rutas a partir de la raíz del proyecto:
from pathlib import Path
RAIZ = Path(__file__).resolve().parents[2]
PROCESADOS = RAIZ / "data" / "processed"
PROCESADOS.mkdir(parents=True, exist_ok=True)
panel = generar_panel()
panel.to_parquet(PROCESADOS / "panel_semanal.parquet", index=False)
print(panel.shape) # (4160, 13)
Parquet conserva los tipos (fechas, enteros, categorías) y es más rápido que CSV. Para una tabla de 4160 filas da igual la velocidad, pero conservar el tipo fecha de semana evita errores al agrupar por año.
5. Qué va al control de versiones y qué no
Git guarda el código, no los datos pesados ni los secretos. Un .gitignore mínimo:
.venv/
__pycache__/
.ipynb_checkpoints/
data/processed/
.env
Los datos crudos grandes van en un almacenamiento aparte y el README documenta de dónde salen y en qué fecha se descargaron. Los tokens de API (Banxico o INEGI, por ejemplo) van en .env y nunca en el notebook.
Trampas comunes
- Editar el CSV crudo «solo una vez». Esa corrección manual no se puede reproducir. Toda limpieza va en código.
- Celdas ejecutadas fuera de orden. Antes de entregar, reinicia el kernel y ejecuta todo de arriba abajo.
- Semillas olvidadas. Sin
np.random.default_rng(42)los datos simulados cambian en cada corrida y las cifras del informe dejan de coincidir. - Un notebook gigante. Si supera unas cuantas decenas de celdas, separa exploración, estimación y reporte en notebooks distintos.
Checklist del proyecto
- Existe
data/rawy nadie lo modifica a mano. - Las dependencias están declaradas con versiones en
pyproject.tomlorequirements.txt. - Hay un entorno virtual y está fuera de Git.
- Las funciones reutilizables viven en
src/y usan semilla fija. - Las rutas se construyen con
pathlibdesde la raíz. - El notebook corre de principio a fin tras reiniciar el kernel.
Con esta estructura lista, cada cifra que aparezca en el curso se puede rastrear hasta una función y una semilla.