RRC / scripts /sync_club_dictionary.py
pablogrois's picture
Claude Opus 5
Integrar el diccionario de variables del club
31157f4
Raw History Blame Contribute Delete
5.8 kB
#!/usr/bin/env python3
"""Sincroniza el diccionario de variables que manda el club con nuestros metadatos.
El club manda un xlsx con cuatro columnas: ``Categoría`` (categoría de estilo de juego),
``Categoria_2`` (subcategoría), ``Nombre`` (nombre de uso) y ``Nombre Columna`` (nombre en el
dataset). Este script lo compara con lo que tenemos y actualiza:
scripts/feature_groups.json ....... agrega (nunca borra) las variables que el club asigna a
una categoría y a nosotros nos faltaba el grupo
scripts/feature_subgroups.json .... columna → subcategoría (``Categoria_2``), info nueva
scripts/var_labels_extra.json ..... se poda: quedan solo los nombres que el club NO da
Después hay que re-correr, en este orden:
python scripts/build_var_dict.py
python webapp-static/build_data.py
python scripts/gen_diccionario_variables.py
python scripts/gen_referencia.py
El xlsx **no está versionado** (`*.xlsx` está en .gitignore porque el repo es público):
guardá el que manda el club en la raíz de racing-reports/ antes de correr esto.
Uso: python scripts/sync_club_dictionary.py [ruta.xlsx] [--dry-run]
"""
from __future__ import annotations
import json
import sys
from pathlib import Path
import pandas as pd
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "src"))
from racing_reports import team_vars # noqa: E402
DEFAULT_XLSX = ROOT / "diccionario_variables_2.xlsx"
GROUPS = ROOT / "scripts" / "feature_groups.json"
SUBGROUPS = ROOT / "scripts" / "feature_subgroups.json"
EXTRA = ROOT / "scripts" / "var_labels_extra.json"
# Categoría del club → nombre del grupo tal como se ve en la app.
CAT_TO_GRUPO = {
"Balón Parado": "Balón parado",
"Balón Parado – Defensivo": "Balón parado (rival)",
"Build-up / Posesión": "Build-up / Posesión",
"Defensiva": "Defensiva",
"Defensiva – Presión": "Defensiva – Presión",
"Disciplina / Control": "Disciplina / Control",
"Ofensiva – Creación": "Ofensiva – Creación",
"Transiciones – Defensivas": "Transiciones – Defensivas",
"Transiciones – Ofensivas": "Transiciones – Ofensivas",
# ESTRATEGIA (formacion / formacion_rival) no entra: no son métricas, van como metadato.
}
def main() -> None:
args = [a for a in sys.argv[1:] if not a.startswith("--")]
dry = "--dry-run" in sys.argv
xlsx = Path(args[0]) if args else DEFAULT_XLSX
dic = pd.read_excel(xlsx, sheet_name=0)
dic["col"] = dic["Nombre Columna"].astype(str).str.strip().str.lower()
dic = dic.rename(columns={"Categoría": "cat", "Categoria_2": "sub", "Nombre": "nombre"})
nuestras = {c.lower() for c in team_vars.variables()}
groups = json.loads(GROUPS.read_text(encoding="utf-8")) if GROUPS.exists() else {}
extra = json.loads(EXTRA.read_text(encoding="utf-8")) if EXTRA.exists() else {}
print(f"[sync] {xlsx.name}: {len(dic)} filas · nuestras variables: {len(nuestras)}")
fuera = dic[~dic["col"].isin(nuestras)]
if len(fuera):
print(f"\n {len(fuera)} variables del club que NO existen en team_stats_agg:")
for r in fuera.itertuples():
print(f" {r.col:32} ({r.nombre})")
# ── grupos: unión ─────────────────────────────────────────────────────────
add, nuevos_grupos = 0, set()
for r in dic[dic["col"].isin(nuestras)].itertuples():
g = CAT_TO_GRUPO.get(str(r.cat).strip())
if not g:
continue
cur = groups.setdefault(r.col, [])
if g not in cur:
cur.append(g)
cur.sort()
add += 1
if g not in {x for v in groups.values() for x in v if v is not cur}:
nuevos_grupos.add(g)
sin_grupo = sorted(c for c in nuestras if not groups.get(c))
print(f"\n grupos agregados: {add}")
print(f" variables sin ningún grupo: {len(sin_grupo)}"
+ (f" → {sin_grupo}" if sin_grupo else ""))
por_grupo = {}
for c, gs in groups.items():
for g in gs:
por_grupo[g] = por_grupo.get(g, 0) + 1
print(" grupos resultantes:")
for g in sorted(por_grupo):
print(f" {g:34} {por_grupo[g]:3}")
# ── subcategorías ─────────────────────────────────────────────────────────
subs = {r.col: str(r.sub).strip()
for r in dic[dic["col"].isin(nuestras)].itertuples()}
print(f"\n subcategorías (Categoria_2): {len(subs)} variables · "
f"{len(set(subs.values()))} valores distintos")
# ── labels: podar var_labels_extra ────────────────────────────────────────
nombrados = set(dic["col"])
sobran = sorted(k for k in extra if k.lower() in nombrados)
quedan = {k: v for k, v in extra.items() if k.lower() not in nombrados}
print(f"\n var_labels_extra: {len(extra)} → {len(quedan)} "
f"({len(sobran)} ya los nombra el club)")
if quedan:
print(f" quedan a mano: {sorted(quedan)}")
if dry:
print("\n[sync] --dry-run: no se escribió nada")
return
GROUPS.write_text(json.dumps(groups, ensure_ascii=False, indent=1), encoding="utf-8")
SUBGROUPS.write_text(json.dumps(dict(sorted(subs.items())), ensure_ascii=False, indent=1),
encoding="utf-8")
EXTRA.write_text(json.dumps(quedan, ensure_ascii=False, indent=1), encoding="utf-8")
print(f"\n[sync] escrito: {GROUPS.name}, {SUBGROUPS.name}, {EXTRA.name}")
if __name__ == "__main__":
main()