---
id: run_eda_models_py_datascience
name: run_eda_models
kind: function
lang: py
domain: datascience
version: "1.0.0"
purity: pure
signature: "def run_eda_models(columns: dict, run_pca: bool = True, run_kmeans: bool = True, run_isolation: bool = True, run_normality: bool = True) -> dict"
description: "Orquesta los modelos baratos del grupo eda (PCA, KMeans, Isolation Forest, normalidad) sobre las columnas numericas de un perfil de tabla y devuelve el bloque models de un TableProfile. Composicion canonica del flag --models de profile_table. Compone funciones puras del registry, no reescribe logica."
tags: [eda, models, datascience, profiling, pca, kmeans, isolation-forest, normality, multivariate, composition]
uses_functions:
  - pca_explained_py_datascience
  - kmeans_segments_py_datascience
  - isolation_forest_outliers_py_datascience
  - normality_tests_py_datascience
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [datascience]
example: |
  from run_eda_models import run_eda_models
  cols = {
      "x": {"values": [1.0, 2.0, 3.0, 4.0], "type": "numeric"},
      "y": {"values": [2.0, 4.0, 6.0, 8.0], "type": "numeric"},
      "z": {"values": [5.0, 4.0, 6.0, 5.5], "type": "numeric"},
  }
  block = run_eda_models(cols)
  # block["n_numeric_cols"] == 3; block["pca"], block["kmeans"], block["normality"] poblados
tested: true
tests:
  - "test_three_numeric_columns_runs_all_models"
  - "test_single_numeric_column_note_and_normality_only"
  - "test_flags_disable_models"
  - "test_no_numeric_columns_returns_note_and_no_normality"
test_file_path: "python/functions/datascience/run_eda_models_test.py"
file_path: "python/functions/datascience/run_eda_models.py"
params:
  - name: columns
    desc: "Mapa {nombre_columna: {values: list, type: 'numeric'|'categorical'|'datetime'|...}}. Mismo shape que recibe association_matrix; listas alineadas por fila. Solo las columnas con type=='numeric' alimentan los modelos."
  - name: run_pca
    desc: "Si True, ejecuta pca_explained sobre el subconjunto numerico (estructura latente / varianza explicada). Default True."
  - name: run_kmeans
    desc: "Si True, ejecuta kmeans_segments con seleccion automatica de k por silhouette (segmentos naturales). Default True."
  - name: run_isolation
    desc: "Si True, ejecuta isolation_forest_outliers (anomalias multivariante). Default True."
  - name: run_normality
    desc: "Si True, ejecuta normality_tests por cada columna numerica. Es univariante: basta 1 columna. Default True."
output: >
  dict con {n_numeric_cols, pca, kmeans, outliers, normality, note}. pca/kmeans/outliers
  son la salida de su funcion del registry o None (flag desactivado o <2 columnas numericas).
  normality es {col: salida de normality_tests} o None (flag desactivado o sin columnas
  numericas). Con <2 columnas numericas los multivariantes quedan en None y note =
  "insuficientes columnas numericas para modelos multivariantes" (normality sigue
  poblandose si hay >=1 columna numerica). Con >=2 columnas y todo activado, note = "".
  Nunca lanza excepcion.
---

## Ejemplo

```python
from run_eda_models import run_eda_models
import numpy as np

rng = np.random.default_rng(0)
n = 120
x = rng.normal(0, 1, n)
y = x * 2 + rng.normal(0, 0.3, n)   # correlacionada con x
z = rng.normal(5, 1, n)             # ruido independiente

cols = {
    "x": {"values": x.tolist(), "type": "numeric"},
    "y": {"values": y.tolist(), "type": "numeric"},
    "z": {"values": z.tolist(), "type": "numeric"},
}

models = run_eda_models(cols)

models["n_numeric_cols"]                         # 3
models["pca"]["explained_variance_ratio"]        # PC1 concentra la varianza de x/y
models["kmeans"]["best_k"]                        # k elegido por silhouette
models["outliers"]["n_outliers"]                  # filas anomalas multivariante
models["normality"]["z"]["is_normal"]             # True (z es normal)
models["note"]                                    # ""

# Una sola columna numerica: solo normalidad, multivariantes en None
solo = {"v": {"values": x.tolist(), "type": "numeric"}}
run_eda_models(solo)["note"]
# "insuficientes columnas numericas para modelos multivariantes"
```

## Cuando usarla

Es la capa `--models` de un EDA: cuando ya tienes el perfil de columnas de una
tabla (mismo shape que alimenta `association_matrix`) y quieres, de un solo golpe,
la estructura latente (PCA), los segmentos naturales (KMeans), las anomalias
multivariante (Isolation Forest) y la normalidad de cada columna numerica. En vez
de llamar a las cuatro funciones por separado y montar el bloque a mano, esta las
compone y devuelve el bloque `models` listo para incrustar en un `TableProfile`.
Usa los flags `run_*` para apagar los modelos que no necesites.

## Gotchas

- PCA, KMeans e Isolation Forest son multivariantes y necesitan **>=2 columnas
  numericas**; con menos, sus claves quedan en `None` y se devuelve `note`. La
  normalidad es univariante y se corre con 1 columna.
- Cada modelo subyacente tiene su propio umbral minimo de filas validas y puede
  devolver `{"note": "datos insuficientes"}` (PCA: >=3 filas; KMeans: >=k_min*2;
  Isolation Forest: >=10 filas; normalidad: >=8 tras limpiar). Esta funcion los
  propaga tal cual dentro del bloque, sin petar.
- Solo se usan columnas con `type == "numeric"`. Los valores se convierten a
  `float` cuando es posible; None, booleanos y no parseables se descartan por
  columna, asi que la longitud efectiva puede ser menor que la lista original.
- `trend_slope` NO se ejecuta aqui: requiere un orden temporal explicito y queda
  disponible suelto en el registry.
- Aunque compone funciones impuras-en-apariencia (sklearn/scipy), todas son
  deterministas (`random_state=0`), por lo que el resultado es reproducible para
  una misma entrada.
