🇬🇧 English · 🇪🇸 Español
Publicación e informes para manuscritos
La investigación macroeconómica exige una comunicación clara y reproducible. Tradicionalmente, trasladar estimaciones empíricas, errores estándar y bandas de confianza desde scripts de Python a artículos académicos requería formateo manual, scripts frágiles o dependencias externas pesadas.
puremacro 2.0 integra una pipeline de generación de informes sin dependencias externas en puremacro.reports y dota a todos los objetos de resultado principales de métodos de exportación nativos para LaTeX, Typst y Markdown.
Los tres ecosistemas de salida
Cada método de exportación en puremacro admite tres formatos principales:
- LaTeX (
.to_latex()): Genera entornos limpios\begin{tabular}...\end{tabular}listos para compilar en Overleaf y plantillas de revistas internacionales (AER, JPE, QJE, REStud). - Typst (
.to_typst()): Produce bloques#table(...)para Typst, el sistema moderno y veloz de composición tipográfica que está ganando amplia adopción en economía y ciencias cuantitativas. - Markdown (
.to_markdown()): Genera tablas en GitHub-Flavored Markdown compatibles con documentos Quarto (.qmd), cuadernos de Jupyter y notas de investigación.
No se requieren librerías de terceros (como tabulate o stargazer). Todo el formateo se realiza mediante funciones ligeras en Python puro compatibles con el contrato de ejecución de Pyodide.
1. Exportación de resultados de estimadores
Proyecciones locales (LPResult)
Todos los estimadores de proyecciones locales (lp_hac, lp_iv, lp_state_dep, lp_state_dep_iv, panel_lp) devuelven un objeto LPResult:
import numpy as np
import pandas as pd
from puremacro.lp import lp_hac
# Un pequeño conjunto trimestral sintético (sustitúyalo por su propio DataFrame)
rng = np.random.default_rng(0)
T = 200
policy_rate = rng.standard_normal(T)
gdp = np.cumsum(-0.15 * policy_rate + 0.3 * rng.standard_normal(T))
df = pd.DataFrame({"gdp": gdp, "policy_rate": policy_rate})
res = lp_hac(df, y="gdp", x="policy_rate", horizon=8, lags=2, ci=0.90)
# Exportar a LaTeX
latex_str = res.to_latex()
# Exportar a Typst
typst_str = res.to_typst()
# Exportar a Markdown
markdown_str = res.to_markdown()
Salida típica para Typst:
#table(
columns: 6,
[* h *],
[* beta *],
[* se *],
[* t *],
[* lo *],
[* hi *],
[0],
[-0.168952],
[0.022707],
[-7.44069],
[-0.206301],
[-0.131603],
[1],
[-0.182836],
[0.030485],
[-5.997644],
[-0.232979],
[-0.132693],
...
)
VAR Estructural (_IRFPlotMixin)
Todos los resultados de SVAR (CholeskySVARResult, ProxySVARResult, SignRestrictionResult, MaxShareResult, etc.) admiten exportación multiformato:
from puremacro.var.identify import cholesky_svar
# VAR(1) de tres variables simulado para el ejemplo
A = np.array([[0.5, 0.1, 0.0], [0.0, 0.4, 0.1], [0.1, 0.0, 0.3]])
Y = np.zeros((300, 3))
for t in range(1, 300):
Y[t] = A @ Y[t - 1] + rng.standard_normal(3)
res = cholesky_svar(Y, p=2, horizon=12, ci=0.90)
# Exportar malla completa de FRI como DataFrame ordenado
df_tidy = res.to_frame()
# Exportar la respuesta de la variable 0 al choque 0
latex_irf = res.to_latex(target_idx=0, shock_idx=0)
typst_irf = res.to_typst(target_idx=0, shock_idx=0)
markdown_irf = res.to_markdown(target_idx=0, shock_idx=0)
VAR aumentado con factores (FAVARResult)
from puremacro.var import favar
# Panel informativo (T x N) y una serie de política, simulados para el ejemplo
factor = np.cumsum(rng.standard_normal(300)) * 0.1
panel_df = pd.DataFrame(
np.outer(factor, rng.uniform(0.5, 1.5, 12)) + 0.3 * rng.standard_normal((300, 12)),
columns=[f"x{i}" for i in range(12)],
)
policy_series = pd.Series(0.5 * factor + 0.2 * rng.standard_normal(300), name="policy_rate")
favar_res = favar(panel_df, policy_series, n_factors=3, horizon=12, n_boot=50)
# Exportar tabla completa de respuestas de corte transversal
print(favar_res.to_latex())
print(favar_res.to_typst())
Resultados de Diferencias en Diferencias
Todas las dataclasses de resultados de DiD escalonado (CallawaySantannaResult, SunAbrahamResult, BorusyakJaravelSpiessResult, SyntheticDiDResult) incorporan .to_markdown(), .to_latex() y .to_typst():
from puremacro.did import callaway_santanna
# Panel con adopción escalonada: 40 unidades, 12 años, cohortes tratadas en 2006 y 2009
rows = []
for i in range(40):
g = {0: 2006, 1: 2009, 2: np.nan}[i % 3]
for year in range(2000, 2012):
effect = 2.0 if (not np.isnan(g) and year >= g) else 0.0
rows.append({"id": i, "year": year, "g": g, "y": 0.1 * (year - 2000) + effect + rng.standard_normal()})
did_df = pd.DataFrame(rows)
res_cs = callaway_santanna(did_df, unit="id", time="year", outcome="y", treat_time="g", n_boot=50)
# Exportar dinámica del estudio de eventos
latex_did = res_cs.to_latex()
typst_did = res_cs.to_typst()
Aprendizaje automático doble (DMLResult)
Nuevo en la 3.4.0. puremacro.causal.dml_plr / DoubleMLPLR devuelven un
DMLResult con los mismos tres exportadores, más .summary():
from puremacro.causal import dml_plr
# Modelo parcialmente lineal: Y = theta*D + g(X) + U, D = m(X) + V
X_dml = rng.standard_normal((500, 30))
D_dml = 0.7 * X_dml[:, 0] + 0.9 * X_dml[:, 1] - 0.4 * X_dml[:, 3] + 0.8 * rng.standard_normal(500)
Y_dml = 1.75 * D_dml + 0.8 * X_dml[:, 0] - 1.0 * X_dml[:, 1] + 0.8 * rng.standard_normal(500)
dml_res = dml_plr(Y_dml, D_dml, X_dml, n_folds=5, learner="lasso", random_state=42)
print(dml_res.summary()) # Bloque de coeficientes al estilo de Stata
markdown_dml = dml_res.to_markdown()
latex_dml = dml_res.to_latex()
typst_dml = dml_res.to_typst()
La tabla LaTeX compila únicamente con booktabs — sin siunitx ni
threeparttable — y escapa los nombres de las variables, de modo que un control
llamado gdp_growth no rompe la compilación. to_markdown() escapa el
encabezado P>|z| para que la barra vertical no parta la columna.
Solucionadores en tiempo continuo (HJBSolution, AiyagariContinuousHJBResult, VFISolution)
También nuevo en la 3.4.0: los objetos de resultado de programación dinámica se
exportan como cualquier estimador. .summary() devuelve un DataFrame de
diagnósticos del solucionador (dimensiones de la malla, iteraciones,
convergencia, error de conservación de masa), .to_frame() devuelve la tabla
completa estado por estado, y .plot() funciona sin entorno gráfico:
from puremacro.vfi import solve_hjb_achdou
sol = solve_hjb_achdou(r_rate=0.03, w_rate=1.0, rho_val=0.05, gamma_r=2.0,
Na=100, a_min=0.0, a_max=30.0)
sol.summary() # Metric / Value: iteraciones, convergencia, error de masa KFE, ...
sol.to_frame() # a_idx, e_idx, asset_a, prod_e, value_V, consumption_c,
# savings_drift_s, density_g
print(sol.to_latex())
VFISolution.to_frame() y .plot() también admiten problemas multiactivo cuyo
a_grid es una lista de mallas de longitudes distintas: la tabla recibe un par
de columnas a_<k> / aprime_<k> por componente, y el gráfico se traza contra
el índice endógeno aplanado.
2. Tablas de regresión independientes (coef_table)
puremacro.reports.coef_table estructura coeficientes y errores estándar arbitrarios en tablas de regresión con estrellas de significancia estadística:
***\(p < 0.01\)**\(p < 0.05\)*\(p < 0.10\)
import numpy as np
from puremacro.reports import coef_table
beta = np.array([0.452, -1.238, 0.081])
se = np.array([0.085, 0.312, 0.074])
names = ["Tasa de interés", "Gasto público", "Recorte de impuestos"]
# 1. Tabla LaTeX con errores entre paréntesis y estrellas
print(coef_table(beta, se, names=names, stars=True, fmt="latex"))
# 2. Tabla Typst
print(coef_table(beta, se, names=names, stars=True, fmt="typst"))
# 3. Tabla Markdown
print(coef_table(beta, se, names=names, stars=True, fmt="markdown"))
Ejemplo de salida en LaTeX:
\begin{tabular}{lrrrrrr}
variable & coef & se & t & p & lo\_95\% & hi\_95\% \\
\hline
Tasa de interés & 0.452*** & 0.085 & 5.318 & 0.000 & 0.285 & 0.619 \\
Gasto público & -1.238*** & 0.312 & -3.968 & 0.000 & -1.850 & -0.626 \\
Recorte de impuestos & 0.081 & 0.074 & 1.095 & 0.274 & -0.064 & 0.226 \\
\end{tabular}
3. Integración en flujos de trabajo de publicación
Quarto (.qmd)
En documentos Quarto, utilice la opción #| output: asis para insertar tablas directamente en documentos PDF o HTML:
```{python}
#| output: asis
from puremacro.lp import lp_hac
res = lp_hac(df, y="gdp", x="shock", horizon=8)
print(res.to_markdown())
### Typst (`.typ`)
Guarde la tabla generada e inclúyala en su archivo principal de Typst:
```python
import os
os.makedirs("tablas", exist_ok=True) # carpeta de tablas del manuscrito
with open("tablas/multiplicadores.typ", "w") as f:
f.write(res.to_typst())
En su documento main.typ: