Spaces:
Build error
Build error
File size: 5,861 Bytes
1003400 |
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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
import gradio as gr
import pandas as pd
from typing import Dict, List, Tuple
from openpyxl.styles import PatternFill, Font
from openpyxl.utils import get_column_letter
from datetime import datetime
def create_encoding_dict(training_df: pd.DataFrame) -> Dict[str, List[str]]:
"""
Crea un diccionario de codificaci贸n basado en el DataFrame de entrenamiento.
Las respuestas pueden tener m煤ltiples c贸digos separados por punto y coma.
"""
encoding_dict = {}
for _, row in training_df.iterrows():
respuesta = str(row['B']).strip().lower()
codigos = str(row['C']).strip().split(';')
codigos = [codigo.strip() for codigo in codigos]
encoding_dict[respuesta] = codigos
return encoding_dict
def find_best_match(respuesta: str, encoding_dict: Dict[str, List[str]]) -> Tuple[List[str], float, str]:
"""
Encuentra la mejor coincidencia para una respuesta en el diccionario de codificaci贸n.
Retorna los c贸digos correspondientes, el score de similitud y la respuesta que hizo match.
"""
from difflib import SequenceMatcher
respuesta = respuesta.strip().lower()
if respuesta in encoding_dict:
return encoding_dict[respuesta], 1.0, respuesta
best_score = 0
best_match = None
for known_resp in encoding_dict.keys():
score = SequenceMatcher(None, respuesta, known_resp).ratio()
if score > best_score:
best_score = score
best_match = known_resp
if best_score > 0.8:
return encoding_dict[best_match], best_score, best_match
return [], 0.0, ""
def format_excel(writer, df, sheet_name="Resultados"):
"""
Da formato al archivo Excel de salida
"""
# Escribimos el DataFrame en el Excel
df.to_excel(writer, sheet_name=sheet_name, index=False)
# Obtenemos la hoja de trabajo
workbook = writer.book
worksheet = writer.sheets[sheet_name]
# Definimos los estilos
header_fill = PatternFill(start_color='366092', end_color='366092', fill_type='solid')
header_font = Font(color='FFFFFF', bold=True)
# Formato para los encabezados
for col in range(len(df.columns)):
cell = worksheet.cell(row=1, column=col+1)
cell.fill = header_fill
cell.font = header_font
# Ajustamos el ancho de las columnas
for col in range(len(df.columns)):
max_length = 0
column = get_column_letter(col + 1)
for cell in worksheet[column]:
try:
if len(str(cell.value)) > max_length:
max_length = len(str(cell.value))
except:
pass
adjusted_width = (max_length + 2)
worksheet.column_dimensions[column].width = min(adjusted_width, 50)
def process_excel(training_file, new_file):
"""
Procesa los archivos de Excel y codifica las nuevas respuestas.
"""
try:
# Leemos los archivos
training_df = pd.read_excel(training_file.name)
new_df = pd.read_excel(new_file.name)
# Creamos el diccionario de codificaci贸n
encoding_dict = create_encoding_dict(training_df)
# Preparamos las columnas de resultado
results_df = new_df.copy()
results_df['C贸digos_Asignados'] = ''
results_df['Score_Similitud'] = 0.0
results_df['Respuesta_Match'] = ''
results_df['Fecha_Proceso'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Procesamos cada respuesta nueva
for idx, row in results_df.iterrows():
respuesta = str(row['B'])
codigos, score, match = find_best_match(respuesta, encoding_dict)
results_df.at[idx, 'C贸digos_Asignados'] = '; '.join(codigos) if codigos else 'SIN_MATCH'
results_df.at[idx, 'Score_Similitud'] = round(score, 2)
results_df.at[idx, 'Respuesta_Match'] = match if match else 'N/A'
# Creamos un resumen
total_respuestas = len(results_df)
respuestas_codificadas = len(results_df[results_df['C贸digos_Asignados'] != 'SIN_MATCH'])
summary_df = pd.DataFrame({
'M茅trica': ['Total Respuestas', 'Respuestas Codificadas', 'Respuestas Sin Match', 'Porcentaje Codificaci贸n'],
'Valor': [
total_respuestas,
respuestas_codificadas,
total_respuestas - respuestas_codificadas,
f"{(respuestas_codificadas/total_respuestas*100):.1f}%"
]
})
# Guardamos el resultado en un Excel con m煤ltiples hojas
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_path = f"resultados_codificacion_{timestamp}.xlsx"
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
# Hoja de resultados detallados
format_excel(writer, results_df, "Resultados")
# Hoja de resumen
format_excel(writer, summary_df, "Resumen")
# Hoja con datos de entrenamiento
format_excel(writer, training_df, "Datos_Entrenamiento")
return output_path
except Exception as e:
return f"Error: {str(e)}"
# Creamos la interfaz de Gradio
iface = gr.Interface(
fn=process_excel,
inputs=[
gr.File(label="Archivo de entrenamiento (Excel)"),
gr.File(label="Archivo a codificar (Excel)")
],
outputs=gr.File(label="Archivo de resultados"),
title="Codificador de Respuestas",
description="Sube un archivo Excel de entrenamiento (con c贸digos conocidos) y un archivo nuevo para codificar las respuestas.",
examples=[],
cache_examples=False
)
# Iniciamos la aplicaci贸n
if __name__ == "__main__":
iface.launch() |