Spaces:
Sleeping
Sleeping
File size: 2,819 Bytes
b8d091a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | """Exportación del análisis completo a un informe Markdown descargable."""
from __future__ import annotations
from datetime import date
import pandas as pd
from . import profiler
def _table_md(df: pd.DataFrame) -> str:
if df.empty:
return "*(sin datos)*\n"
return df.to_markdown(index=False) + "\n"
def build_report(
df: pd.DataFrame,
dataset_name: str,
alerts: list[dict],
target: str | None = None,
insights: str | None = None,
) -> str:
ov = profiler.overview(df)
parts = [
f"# Informe exploratorio — {dataset_name}",
f"*Generado el {date.today().isoformat()} con EDA Express*",
"",
"## Visión general",
f"- **Filas:** {ov['filas']:,} | **Columnas:** {ov['columnas']} "
f"({ov['numericas']} numéricas, {ov['categoricas']} categóricas)",
f"- **Memoria:** {ov['memoria_mb']} MB",
f"- **Faltantes:** {ov['faltantes_total']:,} celdas ({ov['faltantes_pct']}%)",
f"- **Filas duplicadas:** {ov['filas_duplicadas']:,} ({ov['duplicadas_pct']}%)",
"",
"## Alertas de calidad",
]
if alerts:
for a in alerts:
icon = {"critico": "[CRITICO]", "aviso": "[AVISO]", "info": "[INFO]"}[a["nivel"]]
parts.append(f"- {icon} **{a['columna']}** — {a['mensaje']}. {a['recomendacion']}")
else:
parts.append("- Sin alertas: el dataset pasa todas las comprobaciones.")
parts += ["", "## Columnas", _table_md(profiler.column_table(df))]
missing = profiler.missing_table(df)
if not missing.empty:
parts += ["## Valores faltantes", _table_md(missing)]
numeric = profiler.numeric_table(df)
if not numeric.empty:
parts += ["## Variables numéricas", _table_md(numeric)]
categorical = profiler.categorical_table(df)
if not categorical.empty:
parts += ["## Variables categóricas", _table_md(categorical)]
top_corr = profiler.top_correlations(profiler.correlation_matrix(df))
if not top_corr.empty:
parts += ["## Correlaciones más fuertes", _table_md(top_corr)]
if target:
parts += [f"## Análisis respecto a '{target}'"]
if profiler.target_kind(df, target) == "categorico":
parts += ["### Balance de clases", _table_md(profiler.class_balance(df, target))]
corr_target = profiler.correlations_with_target(df, target)
if not corr_target.empty:
parts += ["### Correlación con el objetivo", _table_md(corr_target)]
if insights:
parts += ["## Conclusiones (generadas con LLM)", insights, ""]
parts += [
"---",
"*Los resultados son descriptivos: las decisiones (imputar, eliminar, "
"transformar) requieren conocer el contexto del dato.*",
]
return "\n".join(parts)
|