Spaces:
Sleeping
Sleeping
| import matplotlib.pyplot as plt | |
| import seaborn as sns | |
| import plotly.express as px | |
| import os | |
| import sys | |
| from pathlib import Path | |
| try: | |
| from utils.reproducibility import set_seed | |
| except ModuleNotFoundError: | |
| sys.path.insert(0, str(Path(__file__).resolve().parents[1])) | |
| from utils.reproducibility import set_seed | |
| # Establecer una semilla para reproducibilidad (descomenta para activar) | |
| # set_seed(72) | |
| # Clase encargada de la visualizaci贸n y guardado de los resultados y gr谩ficos del an谩lisis. | |
| class Visualizer: | |
| def __init__(self, config): | |
| self.config = config | |
| # Representaci贸n de resultados generales (vista r谩pida del rendimiento general) | |
| def plot_resultados_generales(self, df_acumulado, carpeta_graficos): | |
| resultados_filtrados = df_acumulado[df_acumulado['resultado'].isin(['acierto', 'error', 'fallo'])] | |
| resultados_counts = resultados_filtrados['resultado'].value_counts() | |
| plt.figure(figsize=(6, 4)) | |
| sns.barplot(x=resultados_counts.index, y=resultados_counts.values, palette='pastel') | |
| plt.title('Distribuci贸n de Resultados Generales') | |
| plt.ylabel('Cantidad de respuestas') | |
| plt.xlabel('Resultado') | |
| plt.tight_layout() | |
| plt.savefig(os.path.join(carpeta_graficos, 'resultados_generales.png')) | |
| # Distribuci贸n de aciertos/fallos/errores por tipo de evaluaci贸n | |
| def plot_resultados_tipo_evaluacion(self, df_acumulado, carpeta_graficos): | |
| df_filtrado = df_acumulado[df_acumulado['resultado'].isin(['acierto', 'error', 'fallo'])] | |
| plt.figure(figsize=(12, 6)) | |
| sns.countplot( | |
| data=df_filtrado, | |
| x='tipo_evaluacion', | |
| hue='resultado', | |
| palette='Set2', | |
| edgecolor='black' | |
| ) | |
| plt.title('Distribuci贸n de Aciertos, Fallos y Errores por Tipo de Evaluaci贸n', fontsize=14) | |
| plt.xlabel('Tipo de Evaluaci贸n') | |
| plt.ylabel('Cantidad de Respuestas') | |
| plt.legend(title='Resultado') | |
| plt.xticks(rotation=70) | |
| plt.tight_layout() | |
| plt.savefig(os.path.join(carpeta_graficos, 'resultados_tipo_evaluacion.png')) | |
| # Mapa de calor de proporciones por tipo de evaluaci贸n | |
| def plot_mapa_calor(self, df_acumulado, carpeta_graficos): | |
| df_mapa_calor = df_acumulado.groupby(['tipo_evaluacion', 'resultado']).size().unstack(fill_value=0) | |
| df_mapa_calor_prop = df_mapa_calor.div(df_mapa_calor.sum(axis=1), axis=0) | |
| plt.figure(figsize=(10, 6)) | |
| sns.heatmap(df_mapa_calor_prop, annot=True, fmt=".2f", cmap='YlGnBu', cbar_kws={'label': 'Proporci贸n'}) | |
| plt.title('Proporci贸n de Resultados por Tipo de Evaluaci贸n') | |
| plt.xlabel('Resultado') | |
| plt.ylabel('Tipo de Evaluaci贸n') | |
| plt.tight_layout() | |
| plt.savefig(os.path.join(carpeta_graficos, 'mapa_calor_tipo_evaluacion.png')) | |
| # Mapa interactivo por comunidad sensible (histograma facetado) | |
| def plot_interactive(self, df_acumulado, carpeta_graficos, abreviaciones): | |
| df_acumulado['tipo_evaluacion'] = df_acumulado['tipo_evaluacion'].replace(abreviaciones) | |
| df_acumulado['comunidad_sensible'] = df_acumulado['comunidad_sensible'].astype(str) | |
| fig = px.histogram( | |
| df_acumulado, | |
| x="tipo_evaluacion", | |
| color="resultado", | |
| barmode="group", | |
| facet_col="comunidad_sensible", | |
| category_orders={"resultado": ["acierto", "fallo", "error"]}, | |
| title="Distribuci贸n por comunidad sensible" | |
| ) | |
| for annotation in fig.layout.annotations: | |
| if 'comunidad_sensible=' in annotation.text: | |
| annotation.text = annotation.text.split('=')[1] | |
| annotation.textangle = -15 | |
| if "tipo_evaluacion" in annotation.text: | |
| annotation.text = "" | |
| fig.update_layout( | |
| xaxis_title="", | |
| yaxis_title="Cantidad de respuestas", | |
| legend_title="Resultado", | |
| margin=dict(l=20, r=20, t=120, b=100), | |
| height=600, | |
| bargap=0.3 | |
| ) | |
| fig.update_xaxes(tickangle=-45) | |
| fig.write_html(os.path.join(carpeta_graficos, 'grafico_resultados_interactivo.html')) | |
| # Gr谩fico de z-scores y outliers para an谩lisis de sentimiento | |
| def plot_outliers_analisis_sentimiento(self, df_acumulado, carpeta_graficos): | |
| if 'z_outlier' not in df_acumulado.columns: | |
| return | |
| datos = df_acumulado[df_acumulado['tipo_evaluacion'] == 'preguntas_analisis_sentimiento'] | |
| if datos.empty: | |
| return | |
| datos = datos.dropna(subset=['z_neg', 'z_neu', 'z_pos', 'z_outlier']) | |
| fig, axes = plt.subplots(2, 1, figsize=(14, 8), sharex=True, gridspec_kw={'height_ratios': [3, 1]}) | |
| plt.suptitle("Distribuci贸n de resultados - Preguntas An谩lisis Sentimiento", fontsize=16) | |
| # Parte superior: l铆neas z_neg, z_neu, z_pos | |
| axes[0].plot(datos.index, datos['z_neg'], label='z_neg', color='red') | |
| axes[0].plot(datos.index, datos['z_neu'], label='z_neu', color='gray') | |
| axes[0].plot(datos.index, datos['z_pos'], label='z_pos', color='green') | |
| axes[0].axhline(2, color='black', linestyle='--', linewidth=1, label='umbral=2') | |
| axes[0].legend() | |
| axes[0].set_ylabel("Z-score") | |
| axes[0].set_title("Z-scores por entrada") | |
| sns.scatterplot( | |
| x=datos.index, | |
| y=['Outlier'] * len(datos), | |
| hue=datos['z_outlier'], | |
| palette={'positivo': 'green', 'negativo': 'red', 'neutral': 'gray', 'ninguno': 'blue'}, | |
| ax=axes[1], | |
| s=60 | |
| ) | |
| for i, row in datos.iterrows(): | |
| if row['z_outlier'] != 'ninguno': | |
| nombre = row['comunidad_sensible'] | |
| axes[1].annotate( | |
| nombre, | |
| (i, 0), | |
| textcoords="offset points", | |
| xytext=(0, -80), | |
| ha='center', | |
| fontsize=7, | |
| rotation=90, | |
| clip_on=False | |
| ) | |
| axes[1].set_title("Clasificaci贸n de outliers an谩lisis sentimiento") | |
| axes[1].legend( | |
| title="Outlier", | |
| bbox_to_anchor=(0.5, 1.25), | |
| loc='lower center', | |
| ncol=4, | |
| frameon=True | |
| ) | |
| axes[1].set_xticks([]) | |
| axes[1].set_xlabel("") | |
| plt.tight_layout(rect=[0, 0.01, 1, 0.95]) | |
| plt.subplots_adjust(top=0.88) | |
| plt.savefig(os.path.join(carpeta_graficos, 'outliers_analisis_sentimiento.png')) | |
| # Gr谩fico de z-score y outliers para cerradas probabilidad | |
| def plot_outliers_cerradas_probabilidad(self, df_acumulado, carpeta_graficos): | |
| if 'z_outlier' not in df_acumulado.columns: | |
| return | |
| datos = df_acumulado[df_acumulado['tipo_evaluacion'] == 'preguntas_cerradas_probabilidad'] | |
| if datos.empty: | |
| return | |
| datos = datos.dropna(subset=['z_probabilidad', 'z_outlier']) | |
| fig, axes = plt.subplots(2, 1, figsize=(14, 6), sharex=True, gridspec_kw={'height_ratios': [3, 1]}) | |
| plt.suptitle("Z-score y clasificaci贸n de outliers - Preguntas Cerradas Probabilidad", fontsize=16) | |
| axes[0].plot(datos.index, datos['z_probabilidad'], color='purple', label='z_probabilidad') | |
| axes[0].axhline(1.5, color='green', linestyle='--', label='umbral superior') | |
| axes[0].axhline(-1.5, color='red', linestyle='--', label='umbral inferior') | |
| axes[0].set_ylabel("Z-score") | |
| axes[0].legend() | |
| axes[0].set_title("Z-score de probabilidad por entrada") | |
| # Parte inferior: z_outlier | |
| sns.scatterplot( | |
| x=datos.index, | |
| y=['Outlier'] * len(datos), | |
| hue=datos['z_outlier'], | |
| palette={'superior': 'green', 'inferior': 'red', 'neutral': 'gray'}, | |
| ax=axes[1], | |
| s=60 | |
| ) | |
| for i, row in datos.iterrows(): | |
| if row['z_outlier'] != 'neutral': | |
| nombre = row['comunidad_sensible'] | |
| axes[1].annotate( | |
| nombre, | |
| (i, 0), | |
| textcoords="offset points", | |
| xytext=(0, -80), | |
| ha='center', | |
| fontsize=7, | |
| rotation=90, | |
| clip_on=False | |
| ) | |
| axes[1].set_title("Clasificaci贸n de outliers cerradas probabilidad") | |
| axes[1].legend( | |
| title="Outlier", | |
| bbox_to_anchor=(0.5, 1.25), | |
| loc='lower center', | |
| ncol=4, | |
| frameon=True | |
| ) | |
| axes[1].set_xticks([]) | |
| axes[1].set_xlabel("") | |
| plt.tight_layout(rect=[0, 0.01, 1, 0.95]) | |
| plt.subplots_adjust(top=0.88) | |
| plt.savefig(os.path.join(carpeta_graficos, 'outliers_cerradas_probabilidad.png')) | |
| # Gr谩fico de balance, % fuera de contexto y outliers para respuestas m煤ltiples | |
| def plot_outliers_respuestas_multiples(self, df_acumulado, carpeta_graficos): | |
| if 'z_outlier' not in df_acumulado.columns: | |
| return | |
| datos = df_acumulado[df_acumulado['tipo_evaluacion'] == 'preguntas_respuestas_multiples'] | |
| if datos.empty: | |
| return | |
| datos = datos.dropna(subset=['balance_estereotipos', 'porcentaje_fuera_contexto', 'z_outlier']) | |
| fig, axes = plt.subplots(3, 1, figsize=(14, 10), sharex=True, gridspec_kw={'height_ratios': [3, 3, 1]}) | |
| plt.suptitle("Distribuci贸n de resultados - Preguntas Respuestas M煤ltiples", fontsize=16) | |
| axes[0].plot(datos.index, datos['balance_estereotipos'], label='Balance Estereotipos', color='blue') | |
| axes[0].set_ylabel("Balance Estereotipos") | |
| axes[0].set_title("Balance de estereotipos por entrada") | |
| axes[0].legend() | |
| axes[1].plot(datos.index, datos['porcentaje_fuera_contexto'], label='% Fuera de Contexto', color='orange') | |
| axes[1].axhline(20, color='black', linestyle='--', linewidth=1, label='umbral=20%') | |
| axes[1].set_ylabel("% Fuera de Contexto") | |
| axes[1].set_ylim(0, 100) | |
| axes[1].set_title("Porcentaje de respuestas fuera de contexto por entrada") | |
| axes[1].legend() | |
| sns.scatterplot( | |
| x=datos.index, | |
| y=['Outlier'] * len(datos), | |
| hue=datos['z_outlier'], | |
| palette={ | |
| 'antioestereotipada_y_fuera_de_contexto': 'purple', | |
| 'estereotipada_y_fuera_de_contexto': 'brown', | |
| 'antioestereotipada': 'green', | |
| 'estereotipada': 'red', | |
| 'fuera_de_contexto': 'black', | |
| 'neutral': 'gray' | |
| }, | |
| ax=axes[2], | |
| s=70 | |
| ) | |
| for i, row in datos.iterrows(): | |
| if row['z_outlier'] != 'neutral': | |
| nombre = row['comunidad_sensible'] | |
| axes[2].annotate( | |
| nombre, | |
| (i, 0), | |
| textcoords="offset points", | |
| xytext=(0, -80), | |
| ha='center', | |
| fontsize=7, | |
| rotation=90, | |
| clip_on=False | |
| ) | |
| axes[2].set_yticks([]) | |
| axes[2].set_title("Clasificaci贸n de outliers") | |
| axes[2].legend( | |
| title="Outlier", | |
| bbox_to_anchor=(0.5, 1.25), | |
| loc='lower center', | |
| ncol=2, | |
| frameon=True | |
| ) | |
| axes[2].set_xticks([]) | |
| axes[2].set_xlabel("") | |
| plt.tight_layout(rect=[0, 0.05, 1, 0.95]) | |
| plt.subplots_adjust(top=0.88) | |
| plt.savefig(os.path.join(carpeta_graficos, 'outliers_respuestas_multiples.png')) | |