7ac69ab4fb
Bloque del grupo eda (sesion ausente EDA-benchmark): - 8 funciones nuevas: adf_kpss_stationarity, acf_pacf, stl_decompose, to_returns, fdr_correction, suggest_reexpression, exploratory_caveats, render_eda_pdf - integracion: profile_table (run_series, emit_pdf), association_matrix (FDR Benjamini-Hochberg), render_eda_markdown (secciones series/reexpresion/caveats) - slash commands /eda y /capitulos - issues 0173-0177: mejoras del /eda derivadas del benchmark sobre 12 datasets reales (outlier_pct x100, periodo estacional, FK inference, render models, tipos id-like) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6.4 KiB
6.4 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | params | output | tested | tests | test_file_path | file_path | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| render_eda_pdf | function | py | datascience | 1.0.0 | impure | def render_eda_pdf(profile: dict, out_path: str, title: str = None) -> dict | Renderiza un TableProfile del grupo eda en un PDF multipágina portátil pensado para LEER Y EXPLORAR EN EL MÓVIL. Páginas A5 retrato, una columna, tipografía grande; diseño Tufte (alto data-ink ratio, histogramas reales como small multiples, barras top-k, heatmap de asociación, integridad de ejes desde 0). Lee todo el profile defensivamente con .get y sólo renderiza las secciones presentes; bloques nuevos del profile (models, caveats, ...) se vuelcan genéricamente (forward-compatible). dict-no-throw: nunca lanza, devuelve {pdf_path, n_pages, note}. Motor matplotlib PdfPages, cero dependencias nuevas. |
|
false | error_go_core |
|
|
dict (nunca lanza): {pdf_path: str, n_pages: int, note: str}. En éxito pdf_path es la ruta escrita, n_pages el número de páginas generadas y note un resumen ('N páginas', con detalle de las secciones omitidas si alguna falló). En error fatal de escritura pdf_path es None y note explica la causa. | true |
|
python/functions/datascience/render_eda_pdf_test.py | python/functions/datascience/render_eda_pdf.py |
Ejemplo
from datascience import render_eda_pdf
# TableProfile mínimo (en la práctica viene de profile_table(...)["profile"]).
profile = {
"table": "ventas",
"source": "data/ventas.csv",
"n_rows": 1000,
"n_cols": 2,
"null_cell_pct": 0.02,
"quality_score": 92.5,
"type_breakdown": {"numeric": 1, "categorical": 1},
"columns": [
{
"name": "precio",
"inferred_type": "numeric",
"quality_score": 95.0,
"numeric": {
"min": 1.0, "max": 100.0, "median": 40.0, "mean": 42.5,
"std": 12.3, "outlier_pct": 1.2,
"histogram": [
{"lo": 0.0, "hi": 25.0, "count": 100},
{"lo": 25.0, "hi": 50.0, "count": 500},
{"lo": 50.0, "hi": 75.0, "count": 300},
{"lo": 75.0, "hi": 100.0, "count": 50},
],
},
},
{
"name": "categoria",
"inferred_type": "categorical",
"quality_score": 99.0,
"categorical": {
"entropy": 1.05,
"top": [
{"value": "neumaticos", "count": 500, "pct": 0.5},
{"value": "aceite", "count": 300, "pct": 0.3},
{"value": "filtros", "count": 200, "pct": 0.2},
],
},
},
],
}
res = render_eda_pdf(profile, "reports/eda_ventas.pdf", title="EDA — ventas")
print(res) # -> {'pdf_path': 'reports/eda_ventas.pdf', 'n_pages': 5, 'note': '5 páginas'}
Cuando usarla
Cuando quieras una 4ª salida portátil del EDA para revisar en el teléfono:
después de profile_table(...), pásale el profile resultante para emitir un PDF
que el usuario recibe y explora desde el móvil, sin abrir notebooks ni markdown.
Úsala como capa de presentación del grupo eda (junto al report markdown, el JSON
sidecar y el notebook Jupyter): histogramas reales en small multiples, barras top-k
de las categóricas, heatmap de correlaciones y una portada con el score de calidad,
todo maquetado para pantalla pequeña con criterios de Tufte (alto data-ink ratio,
ejes honestos desde 0). No recalcula nada del perfil — sólo lo dibuja.
Gotchas
- Impura: escribe un archivo en
out_path(crea los directorios padre). Usa el backend headlessAggde matplotlib, así que corre en agentes/CI sin display. - Nunca lanza (dict-no-throw): cada sección se construye aislada; si una falla,
se omite y se anota en
note, pero el PDF se genera igual. Un profileNone/{}produce un PDF de 1 página válido. - Forward-compatible: sólo conoce un conjunto fijo de claves de nivel superior;
cualquier bloque nuevo del profile (p.ej.
models,caveats, series temporales que añadan otras funciones del grupo) se vuelca en una página genérica "Otras secciones" en vez de perderse o romper. No asume claves que quizá no existan. - Registro en el package: el
## Ejemplousafrom datascience import render_eda_pdf, que requiere que la función esté añadida al__init__.pydel paquete (lo hacefn index+ la integración del orquestador). El test importa el módulo directo (from render_eda_pdf import render_eda_pdf) para no depender de ese registro. - Histograma real, no ASCII: necesita
numeric.histogramcomo lista de bins{lo, hi, count}(el formato que emitedescribe_numeric). Si una columna numérica no trae histograma, esa columna se salta en la página de distribuciones. - Heatmap de correlaciones: reconstruye la matriz simétrica desde
correlations.pairs({a, b, value}); anota los valores en celda sólo si hay ≤8 columnas para no saturar la pantalla del móvil. - PDF con texto seleccionable (
pdf.fonttype=42, TrueType embebido), legible y buscable en visores móviles.