Spaces:
Sleeping
Sleeping
| import os | |
| import pandas as pd | |
| from typing import Tuple, Optional, Dict, List | |
| import datetime | |
| def cargar_dataframe(file_path: str) -> Tuple[Optional[pd.DataFrame], Optional[str]]: | |
| """ | |
| Carga un DataFrame desde múltiples formatos con validación robusta | |
| """ | |
| if not os.path.exists(file_path): | |
| return None, f"Error: El archivo {file_path} no existe" | |
| try: | |
| ext = os.path.splitext(file_path)[1].lower() | |
| if ext == '.csv': | |
| df = pd.read_csv(file_path, encoding='utf-8', na_values=['', 'NA', 'NULL', 'NaN']) | |
| elif ext in ('.xls', '.xlsx'): | |
| df = pd.read_excel(file_path, na_values=['', 'NA', 'NULL', 'NaN']) | |
| elif ext == '.parquet': | |
| df = pd.read_parquet(file_path) | |
| elif ext == '.json': | |
| df = pd.read_json(file_path) | |
| else: | |
| return None, f"Error: Formato {ext} no soportado" | |
| # Convertir strings a categorías para optimización | |
| for col in df.select_dtypes(include=['object']): | |
| if len(df[col].unique()) / len(df[col]) < 0.5: | |
| df[col] = df[col].astype('category') | |
| return df, None | |
| except Exception as e: | |
| return None, f"Error al cargar {file_path}: {str(e)}" | |
| def analizar_nulos_por_columna(df: pd.DataFrame) -> List[Dict]: | |
| """ | |
| Analiza valores nulos por columna con métricas detalladas | |
| Returns: | |
| Lista de diccionarios con: | |
| - nombre_columna | |
| - tipo_dato | |
| - total_nulos | |
| - porcentaje_nulos | |
| - no_nulos | |
| - porcentaje_no_nulos | |
| - ejemplo_valores (3 primeros no nulos) | |
| """ | |
| analisis = [] | |
| total_filas = len(df) | |
| for columna in df.columns: | |
| nulos = df[columna].isnull().sum() | |
| no_nulos = total_filas - nulos | |
| porcentaje_nulos = (nulos / total_filas) * 100 if total_filas > 0 else 0 | |
| valores_unicos = df[columna].nunique() | |
| # Ejemplos de valores (excluyendo nulos) | |
| ejemplos = [] | |
| if no_nulos > 0: | |
| ejemplos = df[columna].dropna().head(3).tolist() | |
| # Convertir a string si es necesario para serialización | |
| ejemplos = [str(x) for x in ejemplos] | |
| analisis.append({ | |
| 'nombre_columna': columna, | |
| 'tipo_dato': str(df[columna].dtype), | |
| 'total_nulos': nulos, | |
| 'porcentaje_nulos': round(porcentaje_nulos, 2), | |
| 'no_nulos': no_nulos, | |
| 'porcentaje_no_nulos': round(100 - porcentaje_nulos, 2), | |
| 'valores_unicos': valores_unicos, | |
| 'ejemplo_valores': ejemplos | |
| }) | |
| # Ordenar por porcentaje de nulos descendente | |
| return sorted(analisis, key=lambda x: x['porcentaje_nulos'], reverse=True) | |
| def get_file_metadata(file_path: str) -> Dict: | |
| """ | |
| Obtiene metadatos detallados del archivo | |
| """ | |
| stats = os.stat(file_path) | |
| return { | |
| 'nombre': os.path.basename(file_path), | |
| 'ruta': os.path.abspath(file_path), | |
| 'tamaño_bytes': stats.st_size, | |
| 'tamaño_mb': round(stats.st_size / (1024 * 1024), 2), | |
| 'fecha_modificacion': datetime.datetime.fromtimestamp(stats.st_mtime), | |
| 'extension': os.path.splitext(file_path)[1].lower(), | |
| 'encoding': 'utf-8' # Se puede detectar con chardet si es necesario | |
| } | |