--- name: kmeans_segments kind: function lang: py domain: datascience version: "1.0.0" purity: pure signature: "def kmeans_segments(columns: dict, k_min: int = 2, k_max: int = 8) -> dict" description: "Detecta segmentos naturales con KMeans eligiendo el mejor k automaticamente por silhouette. Estandariza, descarta filas con None y prueba k de k_min a min(k_max, n_rows-1)." tags: [eda, models, kmeans, clustering, segmentation, silhouette, unsupervised] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "" imports: [numpy, scikit-learn] tested: true tests: ["test_three_separated_blobs_finds_k3", "test_insufficient_rows_returns_note", "test_insufficient_numeric_columns_returns_note", "test_rows_with_none_are_dropped"] test_file_path: "python/functions/datascience/kmeans_segments_test.py" file_path: "python/functions/datascience/kmeans_segments.py" params: - name: columns desc: "dict {col_name: [valores numericos]} con todas las listas alineadas por fila (misma longitud). Solo se usan columnas numericas; las no numericas se ignoran. Las filas con algun None se descartan." - name: k_min desc: "Numero minimo de clusters a probar. Default 2. El minimo efectivo de filas validas requerido es k_min*2." - name: k_max desc: "Numero maximo de clusters a probar. Default 8. Se acota internamente a min(k_max, n_rows_validas-1)." output: "dict con best_k (k de mayor silhouette), silhouette (score del mejor k), scores_by_k (lista de {k, silhouette, inertia} por cada k probado), cluster_sizes (tamano de cada cluster del mejor modelo), centers (centroides en espacio estandarizado), n_rows_used (filas validas) y n_features (columnas numericas). Si hay <2 columnas numericas o