f3d427d9e4
Conecta el motor AutomaticEDA con los datos crudos para que los 4 capítulos
dependientes de ctx (modelos, timeseries, geospatial, agregacion) salgan
POBLADOS en vez de degradar a una nota.
- build_eda_render_ctx (datascience, impure, dict-no-throw): dado db_path+table
y el TableProfile agregado, construye el ctx con los datos crudos que el
perfil no incluye: raw_numeric {col:[float|None]} alineado por fila (modelos /
geospatial), timeseries_raw {time_col,t,series} vía extract_timeseries_raw,
geo_points {lats,lons} desde el par lat/lon detectado, y db_path/table para el
groupby/pivot push-down de agregacion. Muestrea con LIMIT (no trae la tabla
entera a RAM). Compone detect_time_column / extract_timeseries_raw /
detect_latlon_columns / duckdb_query_readonly (imports lazy para evitar ciclo).
- render_automatic_eda (pipeline): one-shot perfil -> ctx -> PDF + PPTX con los
11 capítulos poblados; devuelve rutas + manifest de versiones por capítulo.
- profile_table: flag aditivo emit_automatic=True emite el AutomaticEDA PDF+PPTX
además del flujo legacy (emit_pdf/render_eda_pdf intacto). Nuevas claves de
retorno aeda_pdf_path / aeda_pptx_path / aeda_manifest_path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8.7 KiB
8.7 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 | |||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| build_eda_render_ctx | function | py | datascience | 1.0.0 | impure | def build_eda_render_ctx(db_path: str, table: str, profile: dict, backend: str = 'duckdb', sample: int = 5000, base_ctx: dict = None) -> dict | Constructor del `ctx` de datos crudos del motor AutomaticEDA. Dado un db_path+table (DuckDB o Postgres) y el TableProfile AGREGADO ya calculado por profile_table, produce el dict ctx que los renderers (render_automatic_eda_pdf/_pptx -> build_document(profile, ctx)) pasan a los capitulos que necesitan DATOS CRUDOS no presentes en el perfil agregado: modelos (project_clusters_2d en vivo), timeseries, geospatial y agregacion (groupby/pivot push-down). NO trae tablas enteras a RAM: muestrea con LIMIT sample y delega el push-down de la serie en extract_timeseries_raw. Construye el lector read-only query_fn(sql)->dict igual que profile_table (closure sobre duckdb_query_readonly / pg_query). Estilo dict-no-throw del grupo eda: NUNCA lanza; si una pieza falla, degrada esa clave a ausente/[] y sigue. Devuelve el ctx dict directamente (NO un wrapper {status,...}); se pasa tal cual como meta={'ctx': <ese dict>}. Claves de datos que produce: raw_numeric (muestra cruda alineada por fila), timeseries_raw (fechas+series), geo_points (lats/lons) y db_path+table para el push-down de agregacion. Respeta base_ctx: parte de una copia y solo AÑADE las claves de datos; las de presentacion (dataset_name, source_origin, ...) no se pisan. |
|
|
false | error_go_core |
|
El dict `ctx` directamente (NO un wrapper {status,...}); se pasa tal cual como meta={'ctx': <ese dict>} a render_automatic_eda_pdf/pptx. Nunca lanza. Para backends validos contiene SIEMPRE db_path + table, y opcionalmente: raw_numeric {col:[float|None,...]} (muestra cruda alineada por fila; omitida si no hay numericas o falla la query), timeseries_raw {time_col, t:[iso...], series:{col:[float|None,...]}} (solo si hay columna temporal + numericas y trae filas), geo_points {lats:[...], lons:[...]} (solo si se detecta par lat/lon y ambas estan en raw_numeric). Ante fallo global devuelve al menos {**base_ctx, 'db_path': db_path, 'table': table}. Backend desconocido -> base_ctx tal cual sin claves de datos. | true |
|
python/functions/datascience/build_eda_render_ctx_test.py | python/functions/datascience/build_eda_render_ctx.py |
Ejemplo
import sys, os
sys.path.insert(0, os.path.join("python", "functions"))
from datascience import build_eda_render_ctx, render_automatic_eda_pdf
from datascience import profile_table # opcional: para obtener el TableProfile
# 1) Perfil agregado de la tabla (push-down, sin RAM).
prof = profile_table("data/ventas.duckdb", "ventas_geo", write_report=False)["profile"]
# 2) ctx de datos crudos para los capitulos (muestrea con LIMIT, no carga todo).
ctx = build_eda_render_ctx(
"data/ventas.duckdb", "ventas_geo", prof,
backend="duckdb", sample=5000,
base_ctx={"dataset_name": "Ventas con geolocalizacion"},
)
# ctx == {
# "dataset_name": "Ventas con geolocalizacion", # preservado del base_ctx
# "db_path": "data/ventas.duckdb", "table": "ventas_geo",
# "raw_numeric": {"ventas": [1200.5, ...], "lat": [40.41, ...], "lon": [-3.70, ...]},
# "timeseries_raw": {"time_col": "fecha", "t": ["2024-01-01", ...], "series": {...}},
# "geo_points": {"lats": [40.41, ...], "lons": [-3.70, ...]},
# }
# 3) Se entrega tal cual a los renderers via meta={"ctx": ctx}.
render_automatic_eda_pdf(prof, "reports/eda.pdf", meta={"ctx": ctx})
Cuando usarla
Justo antes de renderizar un AutomaticEDA (PDF o PPTX), cuando ya tienes el
TableProfile AGREGADO de profile_table pero los capitulos de modelos,
timeseries, geospatial y agregacion necesitan DATOS CRUDOS que el perfil
agregado no lleva (la muestra numerica alineada por fila, la serie cronologica,
el par lat/lon, y el db_path/table para el push-down del groupby/pivot). Es el
puente entre el perfil agregado y build_document(profile, ctx): una sola
llamada produce el ctx completo muestreando con LIMIT en vez de cargar la
tabla entera en memoria.
Gotchas
- Impura: lee de la base de datos a traves de
query_fn(closure sobreduckdb_query_readonly/pg_query). No abre conexiones fuera de esos wrappers del registry. Estilo dict-no-throw del grupoeda: NUNCA lanza; ante cualquier fallo (query, deteccion, render de una clave) degrada esa clave a ausente/[]y sigue. Ante un fallo global devuelve al menos{**base_ctx, "db_path": db_path, "table": table}. error_typeen el frontmatter eserror_go_corepor convencion del registry (toda funcion impura debe declararlo y el indexer lo exige), pero el codigo NO lanza esa excepcion: degrada al ctx parcial. Es metadata, no comportamiento.- Devuelve el ctx dict directamente, NO un wrapper
{status,...}: a diferencia deextract_timeseries_raw/profile_table, esta funcion es el ultimo eslabon antes del render y su salida se pasa tal cual comometa={"ctx": <ese dict>}. No envuelvas su retorno. - Backend desconocido: con un
backendque no seaduckdbnipostgresdevuelve elbase_ctxtal cual, SIN claves de datos (ni siquieradb_path/table). Comprueba el backend antes si dependes de esas claves. - Alineacion por fila de
raw_numeric:raw_numeric[col]tiene una entrada por fila muestreada (un valor no convertible a float queda comoNone, no se descarta la fila) porqueproject_clusters_2ddescarta filas listwise: todas las columnas deben tener la MISMA longitud.geo_pointsse construye desderaw_numericpara heredar esa alineacion. geo_pointsexige lat/lon enraw_numeric: el par lat/lon solo se adjunta si ambas columnas se detectaron (nombre+rango) Y figuran enraw_numeric(es decir, son numericas en el perfil). Si la tabla guarda lat/lon como texto no promovido a numeric, no apareceran; el capitulo geospatial sabe degradar.timeseries_rawdepende del orden del backend: hereda elORDER BY "time_col"deextract_timeseries_raw. Si la columna temporal esta guardada como texto no ordenable lexicograficamente (p.ej.DD/MM/YYYY), el orden no sera el cronologico real — normaliza la columna a date/timestamp antes.LIMIT sample: con tablas grandes obtienes el primer tramo (raw_numeric por orden fisico, timeseries por orden cronologico), no un muestreo uniforme. Subesamplesi necesitas mas cobertura.- No loguear los datos crudos:
raw_numeric/timeseries_raw/geo_pointspueden contener datos sensibles. En trazas usa solo conteos y nombres de columna, no el ctx completo.