feat(browser): auto-commit con 178 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
"""PCA rapido sobre columnas numericas para revelar estructura latente.
|
||||
|
||||
Estandariza las columnas (z-score), descarta filas con valores faltantes y
|
||||
ajusta un PCA determinista para ver cuanta varianza concentran pocos
|
||||
componentes. Pensado para exploracion de datos (EDA) barata.
|
||||
"""
|
||||
|
||||
import math
|
||||
|
||||
|
||||
def pca_explained(columns: dict, n_components: int = 2) -> dict:
|
||||
"""Ejecuta PCA sobre columnas numericas y resume la varianza explicada.
|
||||
|
||||
Args:
|
||||
columns: mapa {nombre_columna: [valores numericos]}. Las listas estan
|
||||
alineadas por fila (misma longitud). Las columnas no numericas o
|
||||
con menos de dos valores distintos se descartan.
|
||||
n_components: numero maximo de componentes principales a calcular.
|
||||
Se acota a min(n_features, n_filas_validas).
|
||||
|
||||
Returns:
|
||||
dict con:
|
||||
n_components: numero de componentes realmente calculados.
|
||||
n_rows_used: filas validas usadas (sin None/NaN).
|
||||
n_features: columnas numericas usadas.
|
||||
explained_variance_ratio: varianza explicada por componente.
|
||||
cumulative: varianza acumulada componente a componente.
|
||||
top_loadings: cargas mas grandes (en valor absoluto) por componente.
|
||||
projection: proyeccion de las filas (cap a 1000 filas).
|
||||
Si hay menos de 2 columnas numericas o menos de 3 filas validas,
|
||||
devuelve {n_components: 0, explained_variance_ratio: [],
|
||||
note: "datos insuficientes"} sin lanzar excepcion.
|
||||
"""
|
||||
import numpy as np
|
||||
from sklearn.decomposition import PCA
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
|
||||
insufficient = {
|
||||
"n_components": 0,
|
||||
"explained_variance_ratio": [],
|
||||
"note": "datos insuficientes",
|
||||
}
|
||||
|
||||
if not isinstance(columns, dict) or not columns:
|
||||
return insufficient
|
||||
|
||||
# Quedarnos solo con columnas que se puedan interpretar como numericas.
|
||||
numeric_cols: dict[str, list] = {}
|
||||
for name, values in columns.items():
|
||||
if not isinstance(values, (list, tuple)):
|
||||
continue
|
||||
coerced = []
|
||||
usable = True
|
||||
for v in values:
|
||||
if v is None:
|
||||
coerced.append(math.nan)
|
||||
continue
|
||||
try:
|
||||
f = float(v)
|
||||
except (TypeError, ValueError):
|
||||
usable = False
|
||||
break
|
||||
coerced.append(f)
|
||||
if usable:
|
||||
numeric_cols[name] = coerced
|
||||
|
||||
if len(numeric_cols) < 2:
|
||||
return insufficient
|
||||
|
||||
feature_names = list(numeric_cols.keys())
|
||||
matrix = np.array([numeric_cols[n] for n in feature_names], dtype=float).T
|
||||
|
||||
# Descartar filas con cualquier NaN (incluye los None convertidos).
|
||||
valid_mask = ~np.isnan(matrix).any(axis=1)
|
||||
data = matrix[valid_mask]
|
||||
|
||||
if data.shape[0] < 3:
|
||||
return insufficient
|
||||
|
||||
n_rows_used = int(data.shape[0])
|
||||
n_features = int(data.shape[1])
|
||||
|
||||
k = min(n_components, n_features, n_rows_used)
|
||||
if k < 1:
|
||||
return insufficient
|
||||
|
||||
scaled = StandardScaler().fit_transform(data)
|
||||
pca = PCA(n_components=k, random_state=0)
|
||||
proj = pca.fit_transform(scaled)
|
||||
|
||||
evr = [float(x) for x in pca.explained_variance_ratio_]
|
||||
cumulative = []
|
||||
running = 0.0
|
||||
for x in evr:
|
||||
running += x
|
||||
cumulative.append(float(running))
|
||||
|
||||
# Cargas: una fila por componente, una columna por feature.
|
||||
top_loadings = []
|
||||
for comp_idx, comp in enumerate(pca.components_):
|
||||
order = np.argsort(np.abs(comp))[::-1]
|
||||
for feat_idx in order:
|
||||
top_loadings.append(
|
||||
{
|
||||
"component": int(comp_idx),
|
||||
"feature": feature_names[int(feat_idx)],
|
||||
"loading": float(comp[int(feat_idx)]),
|
||||
}
|
||||
)
|
||||
|
||||
projection = [[float(v) for v in row] for row in proj[:1000]]
|
||||
|
||||
return {
|
||||
"n_components": int(k),
|
||||
"n_rows_used": n_rows_used,
|
||||
"n_features": n_features,
|
||||
"explained_variance_ratio": evr,
|
||||
"cumulative": cumulative,
|
||||
"top_loadings": top_loadings,
|
||||
"projection": projection,
|
||||
}
|
||||
Reference in New Issue
Block a user