Spaces:
Running
Running
Download scripts/sync_club_dictionary.py from pablogrois/RRC: direct link, hf CLI and curl.
- Browser
- Download file 5.8 kB
-
https://huggingface.co/spaces/pablogrois/RRC/resolve/main/scripts/sync_club_dictionary.py
- Command line
-
hf download hf://spaces/pablogrois/RRC/scripts/sync_club_dictionary.py
-
curl -L -o sync_club_dictionary.py https://huggingface.co/spaces/pablogrois/RRC/resolve/main/scripts/sync_club_dictionary.py
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() | |