--- name: detect_time_column kind: function lang: py domain: datascience version: "1.0.0" purity: pure signature: "def detect_time_column(columns: list) -> dict" description: "Detecta, a partir de la lista de ColumnProfile de un TableProfile del grupo eda, cual es la columna de orden temporal y que columnas numericas hay para graficar una serie en el tiempo. Una columna es temporal si inferred_type=='datetime' o semantic_type in {datetime_iso, date_eu}; time_col es la primera temporal en orden. Es la pieza que usa el capitulo TIMESERIES del AutomaticEDA para decidir si aplica. Lectura defensiva dict-no-throw: nunca lanza, siempre devuelve las mismas claves." tags: [eda, timeseries, datetime, profiling, column-detection, automatic-eda, datascience, python] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "" imports: [] params: - name: columns desc: "lista de ColumnProfile dict de un TableProfile del grupo eda. Cada elemento suele tener name, inferred_type, semantic_type y numeric. Elementos que no sean dict se ignoran; None/no-lista/vacia -> dict 'no aplica'." output: "dict SIEMPRE con: time_col (str|None, columna temporal elegida = primera temporal), time_semantic (str, semantic_type de la temporal o ''), numeric_cols (list[str], columnas con inferred_type=='numeric' en orden), n_datetime_cols (int), datetime_cols (list[str], todas las temporales en orden de aparicion), reason (str en espanol explicando la eleccion). Nunca lanza excepcion." tested: true tests: ["test_golden_datetime_y_numericas", "test_deteccion_por_semantic_type_date_eu", "test_sin_columna_temporal", "test_columns_none_no_revienta", "test_columns_vacia_no_revienta", "test_columns_no_lista_no_revienta", "test_elementos_basura_se_ignoran", "test_varias_datetime_elige_la_primera"] test_file_path: "python/functions/datascience/detect_time_column_test.py" file_path: "python/functions/datascience/detect_time_column.py" --- ## Ejemplo ```python from datascience import detect_time_column columns = [ {"name": "fecha", "inferred_type": "datetime", "semantic_type": "datetime_iso"}, {"name": "ventas", "inferred_type": "numeric"}, {"name": "unidades", "inferred_type": "numeric"}, {"name": "region", "inferred_type": "text"}, ] res = detect_time_column(columns) res["time_col"] # -> "fecha" res["numeric_cols"] # -> ["ventas", "unidades"] res["n_datetime_cols"] # -> 1 # Sin columna temporal: el capitulo TIMESERIES no aplica. detect_time_column([{"name": "id", "inferred_type": "numeric"}])["time_col"] # -> None ``` ## Cuando usarla Cuando el capitulo TIMESERIES del AutomaticEDA recibe un TableProfile y necesita decidir si la tabla admite analisis de serie temporal: si `time_col` es None no hay eje de tiempo y el capitulo se salta; si hay `time_col` y `numeric_cols`, úsalas como eje X (orden cronologico) y series Y. Tambien sirve para enrutar el resto del pipeline (acf_pacf / stl_decompose / adf_kpss_stationarity) sobre las columnas numericas detectadas. ## Gotchas - Es pura y stdlib-only (sin numpy ni DuckDB): segura de llamar en cualquier paso. - `time_col` se elige por ORDEN de aparicion en la lista, no por "mejor candidata". Si hay varias columnas datetime y quieres otra, filtra `datetime_cols` tu mismo. - Solo mira metadatos del perfil (`inferred_type`/`semantic_type`); no parsea ni valida los valores reales de la columna. La calidad de la deteccion depende de que el profiler (summarize_table_duckdb / infer_semantic_type) haya inferido bien. - Las claves del semantic_type son exactamente las del profiler: `datetime_iso` (ISO 8601) y `date_eu` (DD/MM/AAAA). Otros formatos de fecha no se detectan por semantic_type salvo que `inferred_type` ya sea `"datetime"`. - `numeric_cols` se basa en `inferred_type == "numeric"` (no en "integer"/"float"); si tu profiler usa otra etiqueta, normalizala antes.