feat(eda): capítulo TIMESERIES del AutomaticEDA (evolución + análisis de serie)
Capítulo nuevo build_timeseries(profile, ctx) -> Chapter|None del motor AutomaticEDA. Cuando la tabla tiene columna de fecha/datetime, grafica la evolución de cada columna numérica por periodo (valor agregado + conteo de filas) y los paneles de descomposición STL y autocorrelación (ACF), con el análisis de la serie: estacionariedad (ADF+KPSS), autocorrelación (Ljung-Box), fuerzas de tendencia/estacionalidad (Hyndman) y la transformación sugerida (retornos o diferencias) para evitar correlaciones espurias. Sin columna temporal devuelve None. Consolida series OHLC casi idénticas en un único gráfico conservando el análisis de cada columna. La serie cruda llega por ctx['timeseries_raw'] (mismo patrón que modelos con raw_numeric); las figuras son perezosas (Figure.make) y el paginador del núcleo garantiza no-corte en PDF y PPTX. CHAPTER_VERSION 1.0.0. Cubre los MUST del diseño (report 2043): MUST-9.1 (línea valor-vs-tiempo + conteo por periodo), MUST-9.2 (paneles STL + ACF), MUST-9.3 (perfil datetime + consolidación OHLC). Funciones nuevas del registry (grupo eda), delegadas a fn-constructor, no inline: - detect_time_column (pure): detecta la columna temporal y las numéricas - profile_datetime (pure): rango/frecuencia/regularidad/huecos de la fecha - resample_timeseries (pure): agrega la serie por periodo + conteo - extract_timeseries_raw (impure): lee la serie cruda ordenada de DuckDB/PG Verificación: 69 tests verdes (capítulo 9 + funciones 28 + núcleo/renderers); golden real sobre seattle-weather (estacional) y aapl (OHLC) con PDF+PPTX sin cortar nada (cols_cortadas=[]). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
---
|
||||
name: profile_datetime
|
||||
kind: function
|
||||
lang: py
|
||||
domain: datascience
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "def profile_datetime(values: list) -> dict"
|
||||
description: "Perfil minimo de una columna fecha/datetime para la cabecera del capitulo TIMESERIES de AutomaticEDA. Acepta datetime.date, datetime.datetime y strings ISO mezclados, parsea defensivamente e ignora lo no parseable (nunca lanza). Devuelve rango (min/max ISO), n, n_distinct, span_days, frecuencia inferida (daily/weekly/monthly/quarterly/yearly/irregular/unknown) a partir del paso mediano entre fechas distintas, is_regular (pasos ~constantes), n_gaps (huecos en la rejilla) y median_step_days. Solo stdlib (datetime + statistics)."
|
||||
tags: [statistics, timeseries, datetime, profiling, frequency, eda, automatic_eda, python]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: [datetime, statistics]
|
||||
params:
|
||||
- name: values
|
||||
desc: "lista de valores fecha. Acepta datetime.date, datetime.datetime y strings ISO ('2021-06-28', '2021-06-28T00:00:00', '2021-06-28 12:00:00'). None, vacios y no parseables se ignoran; tz-aware se normaliza a naive. Si values es None o no iterable se trata como lista vacia."
|
||||
output: "dict SIEMPRE presente con: 'min'/'max' (ISO date YYYY-MM-DD o None), 'n' (valores parseables), 'n_distinct' (fechas unicas), 'span_days' (float o None), 'freq' (daily|weekly|monthly|quarterly|yearly|irregular|unknown), 'is_regular' (bool), 'n_gaps' (int), 'median_step_days' (float o None) y 'note' (str). Con <2 valores o una sola fecha distinta: freq='unknown', is_regular=False, n_gaps=0, median_step_days=None y nota. Nunca lanza."
|
||||
tested: true
|
||||
tests: ["test_serie_diaria_regular_golden", "test_serie_mensual_freq_monthly", "test_serie_con_hueco_cuenta_gaps", "test_strings_iso_mezclados_con_datetime", "test_lista_vacia_y_none_devuelve_unknown", "test_valores_no_parseables_ignorados", "test_span_days_correcto", "test_una_sola_fecha_es_coherente"]
|
||||
test_file_path: "python/functions/datascience/profile_datetime_test.py"
|
||||
file_path: "python/functions/datascience/profile_datetime.py"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```python
|
||||
from datascience import profile_datetime
|
||||
from datetime import date, datetime, timedelta
|
||||
|
||||
# Serie diaria regular de 30 dias
|
||||
fechas = [date(2021, 1, 1) + timedelta(days=i) for i in range(30)]
|
||||
res = profile_datetime(fechas)
|
||||
res["freq"] # -> "daily"
|
||||
res["is_regular"] # -> True
|
||||
res["n_gaps"] # -> 0
|
||||
res["min"], res["max"] # -> ("2021-01-01", "2021-01-30")
|
||||
res["span_days"] # -> 29.0
|
||||
|
||||
# Acepta strings ISO mezclados con objetos datetime/date; ignora lo no parseable
|
||||
profile_datetime(["2021-06-28", datetime(2021, 6, 29, 12), "basura", None])["n"] # -> 2
|
||||
|
||||
# Columna vacia o sin fechas validas
|
||||
profile_datetime([])["freq"] # -> "unknown" + note "datos insuficientes"
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando construyes la cabecera del capitulo TIMESERIES de un EDA y necesitas
|
||||
caracterizar la columna de fecha antes de modelar: que rango cubre, cada cuanto
|
||||
llegan los datos (frecuencia), si la cadencia es regular y si hay huecos en la
|
||||
rejilla temporal. Es el complemento de fecha al perfil numerico/categorico del
|
||||
TableProfile (cierra el `datetime{}=None` pendiente). Pasale la columna de fechas
|
||||
en bruto (tal cual venga de la BD: dates, datetimes o strings ISO) y usa `freq` +
|
||||
`is_regular` + `n_gaps` para decidir si conviene resamplear, rellenar huecos o
|
||||
desestacionalizar mas adelante.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Es pura y stdlib-only, pero la inferencia de `freq` es heuristica por bandas
|
||||
sobre el **paso mediano entre fechas distintas** (se deduplica antes de medir).
|
||||
Cualquier paso fuera de las bandas conocidas (incluido sub-diario, p.ej. datos
|
||||
horarios) cae en `"irregular"`: no hay banda hourly.
|
||||
- El analisis de frecuencia/regularidad/huecos necesita **>=2 fechas distintas**.
|
||||
Con 0-1 valores parseables o una sola fecha unica, `freq="unknown"`,
|
||||
`median_step_days=None` y `n_gaps=0`, pero `min`/`max`/`span_days` siguen siendo
|
||||
coherentes si hay al menos una fecha.
|
||||
- `min`/`max` se reportan como ISO **date** (`YYYY-MM-DD`); la hora se conserva
|
||||
internamente para calcular `span_days` y `median_step_days` (que pueden ser
|
||||
fraccionarios con datetimes sub-diarios) pero no aparece en min/max.
|
||||
- Los datetime con zona horaria se normalizan a naive (se descarta el tzinfo) para
|
||||
poder mezclarlos con fechas naive sin que las restas lancen; esto puede desplazar
|
||||
la fecha en datetimes con offset grande. Para EDA es despreciable.
|
||||
- `is_regular` usa tolerancia ±25% sobre el paso mediano y umbral del 80% de los
|
||||
pasos dentro de banda; series de "primero de mes" (deltas 28-31) salen regulares.
|
||||
- `n_gaps` solo se calcula cuando `freq` es una rejilla regular conocida; con
|
||||
`freq` `"irregular"` o `"unknown"` siempre es 0.
|
||||
Reference in New Issue
Block a user