{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"tpu1vmV38","dataSources":[{"sourceId":59093,"databundleVersionId":7469972,"sourceType":"competition"}],"dockerImageVersionId":30635,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Importaciones","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport time\nimport os\nimport sys\nimport time","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"##### Corremos un cronometro","metadata":{}},{"cell_type":"code","source":"tiempo_inicial = time.time()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Configuración para Visualización Completa de Columnas en DataFrames de Pandas\n\nHabilitar la Visualización de Todas las Columnas en DataFrames: Aquí, utilizamos **pd.set_option('display.max_columns', None)** para ajustar las opciones de visualización en pandas. Esta configuración específica permite que todas las columnas de un DataFrame sean visibles cuando lo imprimimos o lo inspeccionamos en el notebook.\n\nEste ajuste es particularmente **valioso en la fase de análisis exploratorio de datos**, donde queremos tener una **visión completa de nuestros datos** y no perder ninguna columna importante durante la inspección visual. Nos permite tener una mejor comprensión del conjunto de datos con el que estamos trabajando, especialmente cuando se trata de conjuntos de datos con un gran número de características o columnas.","metadata":{}},{"cell_type":"code","source":"# configs\npd.set_option('display.max_columns', None) # we want to display all columns in this notebook\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Carga de Datos de Entrenamiento y Prueba: ","metadata":{}},{"cell_type":"code","source":"train_df = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/train.csv')\ntest_df = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/test.csv')\nsample_submission_df = pd.read_csv('/kaggle/input/hms-harmful-brain-activity-classification/sample_submission.csv')\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_submission_df","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Verificación del Directorio de Trabajo y Listado de Archivos EEG\n\n**Verificación del Directorio de Trabajo Actual:** \nComenzamos obteniendo la ruta del directorio de trabajo actual utilizando **os.getcwd()**. Esto es importante para asegurarnos de que estamos trabajando en el directorio correcto, lo cual es esencial en la gestión de archivos y directorios, especialmente cuando las rutas relativas son una parte crítica de nuestro flujo de trabajo.\n\n**Listado de Archivos en el Directorio Especificado:** \nLuego, listamos los archivos en el subdirectorio **'train_eegs'** usando **os.listdir()**. Esto nos permite ver qué archivos de encefalogramas **(EEG)** tenemos disponibles para trabajar. Es un paso crucial para garantizar que los archivos de datos necesarios están presentes y accesibles en nuestro entorno de trabajo, y nos da una idea inicial sobre la cantidad y el tipo de datos con los que vamos a interactuar.\n\nEstos pasos son esenciales en la fase inicial de cualquier proyecto de ciencia de datos. Nos aseguramos de que estamos en el lugar correcto y tenemos todo lo necesario para comenzar nuestro análisis y procesamiento de datos.","metadata":{}},{"cell_type":"code","source":"# Verificar el directorio de trabajo actual\ncurrent_directory = os.getcwd()\nprint(f\"Directorio de trabajo actual: {current_directory}\")\n\n# Listar archivos en el directorio especificado\neeg_files = os.listdir('/kaggle/input/hms-harmful-brain-activity-classification/train_eegs')\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Carga de un Archivo EEG de Muestra y Estimación del Uso de Memoria\n\n**Carga de un Archivo EEG de Muestra:** \nPrimero, cargamos un archivo de encefalograma **(EEG)** de muestra en un DataFrame utilizando **pd.read_parquet(file_path)**. Seleccionamos el primer archivo de la lista eeg_files que hemos obtenido previamente. Este paso es crucial para empezar a interactuar con nuestros datos EEG y entender su estructura y contenido.\n\n**Estimación del Uso de Memoria del DataFrame:** \nLuego, calculamos cuánta **memoria** está utilizando el **DataFrame eeg_data_sample** en megabytes (MB), usando **sys.getsizeof()**. Este cálculo nos ayuda a entender el impacto en la memoria de nuestro sistema al trabajar con estos datos. Es un aspecto importante a tener en cuenta, especialmente cuando se manejan grandes conjuntos de datos, para asegurarnos de que nuestro entorno de trabajo puede manejarlos eficientemente.","metadata":{}},{"cell_type":"code","source":"import os\nimport pandas as pd\n\n# Asegúrate de que la ruta refleje la ubicación correcta de tus archivos en Kaggle\ndirectorio_datos = '/kaggle/input/hms-harmful-brain-activity-classification/train_eegs'\n\n# Verifica si el directorio realmente existe\nif os.path.isdir(directorio_datos):\n    eeg_files = os.listdir(directorio_datos)\n    # Asegúrate de que hay archivos en el directorio\n    if eeg_files:\n        file_path = f'{directorio_datos}/{eeg_files[0]}'\n        eeg_data_sample = pd.read_parquet(file_path)\n        print(eeg_data_sample)\n    else:\n        print(\"No hay archivos en el directorio especificado.\")\nelse:\n    print(f\"El directorio {directorio_datos} no existe.\")\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Filtrado y Listado de Archivos EEG en Formato Parquet\n\n**Verificación del Directorio de Archivos EEG:**\nInicialmente, establecemos y verificamos que el directorio **'train_eegs'** es el directorio correcto donde esperamos encontrar nuestros archivos de EEG. Al asignar este directorio a la variable directorio, nos preparamos para realizar operaciones con los archivos que contiene.\n\n**Filtrado y Listado de Archivos Parquet:**\nA continuación, aplicamos un filtro para listar solo aquellos archivos en el directorio **'train_eegs'** que terminan con la extensión **'.parquet'**. Esto se logra mediante una comprensión de lista que examina todos los archivos en el directorio y selecciona solo los que cumplen con el criterio de tener la extensión '.parquet'. Este paso es esencial para concentrarnos en los archivos relevantes para nuestro análisis, ignorando cualquier otro tipo de archivo que pueda estar presente.\n\nImpresión de una Muestra de los Archivos Filtrados: Finalmente, imprimimos los primeros cinco archivos de la lista eeg_files. Esto nos sirve como una verificación rápida para asegurarnos de que nuestra lista contiene los archivos correctos y de que el proceso de filtrado ha funcionado adecuadamente.","metadata":{}},{"cell_type":"code","source":"# Asegúrate de que el directorio 'train_eegs' esté correctamente especificado\ndirectorio = '/kaggle/input/hms-harmful-brain-activity-classification/train_eegs'\n\n# Lista todos los archivos en el directorio que terminan con '.parquet'\neeg_files = [archivo for archivo in os.listdir(directorio) if archivo.endswith('.parquet')]\n\n# Imprime los primeros elementos para verificar\nprint(eeg_files[:5])\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Carga de un Archivo EEG de Muestra y Estimación del Uso de Memoria\n\n**Carga de un Archivo EEG de Muestra:** Primero, cargamos un archivo de encefalograma **(EEG)** de muestra para explorar los datos. Utilizamos **pd.read_parquet(file_path)** para leer el archivo **Parquet** correspondiente al primer elemento de nuestra lista **eeg_files**. Este paso es **vital**para comenzar a interactuar con los **datos reales** y entender cómo están estructurados en el formato **Parquet.**\n\n**Estimación del Uso de Memoria del DataFrame:** Tras cargar los datos en un DataFrame de pandas, calculamos el tamaño en memoria del mismo usando **sys.getsizeof(eeg_data_sample)**. Convertimos este tamaño a **megabytes** para una mejor comprensión. Este paso es **crucial**, ya que nos proporciona una idea del **consumo de memoria** asociado con el manejo de estos datos. ","metadata":{}},{"cell_type":"code","source":"# Cargar un archivo de muestra\nfile_path = f'/kaggle/input/hms-harmful-brain-activity-classification/train_eegs/{eeg_files[0]}'\neeg_data_sample = pd.read_parquet(file_path)\n\n# Estimar el uso de memoria\nmemory_usage = sys.getsizeof(eeg_data_sample) / (1024 ** 2)  # en MB\nprint(f\"Uso de memoria para un archivo: {memory_usage:.2f} MB\")\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Cálculo del Tamaño de Lote para el Procesamiento de Datos Basado en el Límite de Memoria\n\n**Establecimiento del Límite de Memoria:**\nDefinimos un límite de memoria **(memory_limit)**, en este caso, **500 MB**. Este valor es el máximo de memoria que estamos dispuestos a asignar para el procesamiento de los datos. Establecer un límite de memoria es una práctica importante en el manejo de grandes volúmenes de datos, ya que ayuda a prevenir problemas como el agotamiento de la memoria y asegura un uso eficiente de los recursos del sistema.\n\n**Cálculo del Tamaño de Lote:**\nUtilizamos el límite de memoria y el uso de memoria estimado por archivo (calculado previamente) para determinar el tamaño de lote **(batch_size)**. El tamaño de lote representa cuántos archivos podemos procesar simultáneamente sin exceder el límite de memoria establecido. Este cálculo es fundamental para implementar técnicas de procesamiento por lotes, lo cual es especialmente útil cuando los conjuntos de datos son demasiado grandes para ser procesados en su totalidad de una sola vez.\n","metadata":{}},{"cell_type":"code","source":"memory_limit = 500  # Establece un límite de memoria en MB, por ejemplo, 500 MB\nbatch_size = int(memory_limit / memory_usage)\nprint(f\"Tamaño de lote estimado: {batch_size}\")\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Procesamiento y Guardado de Datos EEG por Lotes\n\n**Definición de la Función de Procesamiento por Lotes:**\nLa función **process_and_save_batches** toma una lista de archivos **(file_list)**, un tamaño de lote **(batch_size)**, y un directorio opcional donde guardar los lotes procesados. Esta función es **clave para manejar grandes volúmenes de datos** de forma eficiente, procesándolos en segmentos más pequeños que se ajustan a nuestras limitaciones de memoria.\n\n**Manejo de Excepciones y Guardado de Datos:**\nDurante el proceso de lectura, implementamos un manejo de **excepciones** para evitar que **errores** en archivos individuales detengan todo el proceso. Después de procesar cada lote, guardamos el DataFrame concatenado en un archivo **Parquet** en el directorio especificado. Esto no solo **reduce el consumo de memoria** durante el procesamiento, sino que también facilita la reanudación del trabajo y el análisis en etapas posteriores.\n\n**Medición del Tiempo de Procesamiento:** \nLa función registra y muestra el tiempo que toma procesar cada lote y el tiempo total de procesamiento. Esto es útil para monitorear la eficiencia de nuestro proceso y realizar ajustes si es necesario.\n\n**Ejecución de la Función con un Tamaño de Lote Ajustado:**\nFinalmente, ajustamos el **batch_size** si es necesario y ejecutamos la función con nuestra lista de archivos **EEG.** Este paso pone en práctica todo el proceso de procesamiento por lotes que hemos definido.","metadata":{}},{"cell_type":"code","source":"def process_and_save_batches(file_list, batch_size, directory=\"processed_batches\"):\n    total_files = len(file_list)\n    start_time_total = time.time()\n    os.makedirs(directory, exist_ok=True)\n\n    for i in range(0, total_files, batch_size):\n        start_time_batch = time.time()\n        batch_files = file_list[i:i + batch_size]\n        batch_data = []\n\n        for file in batch_files:\n            try:\n                file_path = f'/kaggle/input/hms-harmful-brain-activity-classification/train_eegs/{file}'\n                eeg_data = pd.read_parquet(file_path)\n                batch_data.append(eeg_data)\n                print(f'Archivo {file} cargado con éxito')\n            except Exception as e:\n                print(f'Error al cargar el archivo {file}: {e}')\n\n        # Guardar cada lote procesado como un archivo separado\n        batch_concatenated = pd.concat(batch_data, ignore_index=True)\n        batch_concatenated.to_parquet(f\"{directory}/batch_{i // batch_size + 1}.parquet\")\n\n        end_time_batch = time.time()\n        print(f\"Tiempo de procesamiento del lote {i // batch_size + 1}: {end_time_batch - start_time_batch} segundos\")\n\n    end_time_total = time.time()\n    print(f\"Tiempo total de procesamiento: {end_time_total - start_time_total} segundos\")\n\n# Reducir el tamaño del lote si es necesario\nbatch_size = 300  # Ajusta este número según sea necesario\nprocess_and_save_batches(eeg_files, batch_size)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Combinación de Lotes Procesados en Tres DataFrames Separados\n\n**Función para Combinar Lotes Procesados:**\nLa **función combinar_lotes_procesados_en_tres_dataframes** toma como entrada el directorio donde se almacenan los lotes procesados. Esta función es **crucial** cuando se trabaja con una **cantidad considerable de archivos de datos** que, si se combinan en un único DataFrame, podrían exceder la capacidad de **memoria.**\n\n**Manejo de Excepciones y Medición del Tiempo:**\nImplementamos el **manejo de excepciones** para asegurar que **errores en archivos individuales** no detengan todo el proceso. Además, medimos el tiempo total que toma combinar todos los lotes, lo que nos proporciona una indicación útil sobre la eficiencia del proceso.\n\n**Ejecución de la Función y Verificación de los Resultados:**\nDespués de definir la función, la ejecutamos para el directorio que contiene nuestros lotes procesados. Seguidamente, imprimimos las primeras filas de cada uno de los tres DataFrames combinados para verificar que los datos se han cargado y combinado correctamente.\n\nEste método es una estrategia efectiva para manejar grandes volúmenes de datos en situaciones donde cargar todo en un único DataFrame no es viable debido a limitaciones de memoria. Permite una gestión más flexible y escalable de los datos, facilitando el análisis posterior en segmentos más manejables.","metadata":{}},{"cell_type":"code","source":"def combinar_lotes_procesados_en_tres_dataframes(directorio):\n    archivos_de_lotes = [archivo for archivo in os.listdir(directorio) if archivo.endswith('.parquet')]\n    todos_los_datos_1 = pd.DataFrame()\n    todos_los_datos_2 = pd.DataFrame()\n    todos_los_datos_3 = pd.DataFrame()\n    start_time = time.time()\n\n    for i, archivo in enumerate(archivos_de_lotes):\n        try:\n            ruta_completa = os.path.join(directorio, archivo)\n            datos_lote = pd.read_parquet(ruta_completa)\n\n            # Dividir los datos en tres DataFrames\n            if i < 20:\n                todos_los_datos_1 = pd.concat([todos_los_datos_1, datos_lote], ignore_index=True)\n            elif i < 40:\n                todos_los_datos_2 = pd.concat([todos_los_datos_2, datos_lote], ignore_index=True)\n            else:\n                todos_los_datos_3 = pd.concat([todos_los_datos_3, datos_lote], ignore_index=True)\n        except Exception as e:\n            print(f\"Error al procesar el archivo {archivo}: {e}\")\n\n    end_time = time.time()\n    print(f\"Tiempo total de procesamiento: {end_time - start_time} segundos\")\n    return todos_los_datos_1, todos_los_datos_2, todos_los_datos_3\n\n# Directorio donde guardaste los lotes procesados\ndirectorio_lotes = \"processed_batches\"\n\ntry:\n    # Combinar todos los lotes en tres DataFrames\n    datos_combinados_1, datos_combinados_2, datos_combinados_3 = combinar_lotes_procesados_en_tres_dataframes(directorio_lotes)\n    # Opcional: revisar los primeros registros para confirmar\n    print(datos_combinados_1.head())\n    print(datos_combinados_2.head())\n    print(datos_combinados_3.head())\nexcept Exception as e:\n    print(f\"Error durante la combinación de lotes: {e}\")\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datos_combinados_1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datos_combinados_1.info()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datos_combinados_1.describe()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Generación y Visualización de Histogramas para el DataFrame de Datos Combinados\n\n**Generación de Histogramas para Todas las Columnas:**\nUtilizamos el método **hist** de **pandas** en datos_combinados_1 para generar histogramas de todas las columnas. Este método es **extremadamente útil** para la exploración de datos, ya que nos permite visualizar rápidamente la distribución de los datos en cada columna. Establecemos el tamaño de la figura en (20, 15) para asegurar que los histogramas sean lo suficientemente grandes y claros, y usamos bins=50 para definir el número de barras (o \"bins\") en cada histograma, lo cual afecta a la granularidad de la visualización.\n\n**Visualización de los Histogramas:**\nDespués de generar los histogramas, utilizamos **plt.show() de Matplotlib** para mostrarlos. Esto nos brinda una representación gráfica que puede revelar patrones interesantes, anomalías, distribuciones sesgadas o la presencia de valores atípicos en nuestros datos.\n\nEsta técnica es una parte **integral del análisis exploratorio de datos**, ya que los histogramas son herramientas poderosas para comprender la naturaleza y las características de los datos con los que estamos trabajando. Nos permiten identificar tendencias y características clave que podrían influir en posteriores etapas de modelado o análisis más detallado.\n","metadata":{}},{"cell_type":"code","source":"# Generar histogramas para todas las columnas en el DataFrame\ndatos_combinados_1.hist(figsize=(20, 15), bins=50)\n\n# Mostrar los histogramas\nplt.show()\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"###  Filtrado Global de Datos Usando Percentiles y Restablecimiento del Índice\n\n**Inicialización de un Filtro Global:**\nComenzamos estableciendo **filtro_global** como un array de valores True, con la misma longitud que el número de filas en datos_combinados_1. Este filtro actuará como una máscara booleana para seleccionar filas que cumplen con ciertos criterios en todas las columnas.\n\n**Cálculo de Percentiles y Actualización del Filtro Global:**\nIteramos sobre cada columna del DataFrame y calculamos los **percentiles 10 y 90**. Luego, actualizamos **filtro_global** para incluir solo aquellas filas donde los valores de la columna actual están dentro del rango interpercentil (entre el percentil 10 y 90). Utilizamos un operador **&=** para asegurarnos de que una fila debe cumplir con los criterios de filtrado en todas las columnas para ser retenida.\n\n**Aplicación del Filtro Global al DataFrame:**\nDespués de actualizar **filtro_globa**l para todas las columnas, aplicamos este filtro a datos_combinados_1. Esto efectivamente **elimina todas las filas que tienen valores atípicos en cualquier columna.**\n\n**Restablecimiento del Índice del DataFrame:**\nComo el filtrado puede haber eliminado algunas filas, restablecemos el índice del DataFrame para **mantener la consistencia** y asegurarnos de que no haya huecos o índices desordenados. Usamos **reset_index(drop=True, inplace=True)** para lograr esto.\n\nEste método de filtrado global es particularmente útil cuando queremos asegurarnos de que los datos en todas las columnas estén dentro de un rango razonable y deseamos evitar la influencia de valores atípicos en el análisis posterior. Al final de este proceso, datos_combinados_1 contiene datos más consistentes y representativos para su uso en análisis estadísticos o modelos predictivos.\n\n\n\n","metadata":{}},{"cell_type":"code","source":"# Inicializar un filtro global como True para todas las filas\nfiltro_global = [True] * len(datos_combinados_1)\n\nfor columna in datos_combinados_1.columns:\n    # Calcular percentiles para cada columna\n    percentil_10 = datos_combinados_1[columna].quantile(0.10)\n    percentil_90 = datos_combinados_1[columna].quantile(0.90)\n    \n    # Actualizar el filtro global para cada columna\n    filtro_global &= (datos_combinados_1[columna] >= percentil_10) & (datos_combinados_1[columna] <= percentil_90)\n\n# Aplicar el filtro global al DataFrame\ndatos_combinados_1 = datos_combinados_1[filtro_global]\n\n# Restablecer el índice después de filtrar\ndatos_combinados_1.reset_index(drop=True, inplace=True)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datos_combinados_1.describe()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Generación de Histogramas para Cada Columna","metadata":{}},{"cell_type":"code","source":"# Generar histogramas para todas las columnas en el DataFrame\ndatos_combinados_1.hist(figsize=(20, 15), bins=50)\n\n# Mostrar los histogramas\nplt.show()\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Generación del Histograma para la Columna 'Fp1 '(como prueba)","metadata":{}},{"cell_type":"code","source":"# Creando un histograma para visualizar la frecuencia de valores en la columna 'Fp1'\ndatos_combinados_1['Fp1'].hist(bins=20)  # Puedes ajustar el número de bins según tus necesidades\nplt.title('Distribución de Valores en Fp1')\nplt.xlabel('Valor en Fp1')\nplt.ylabel('Frecuencia')\nplt.show()\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Cambiar nonmbre de las columnas\n\nLa variable **nombres_actuales** contiene una lista de los nombres actuales de las columnas en el DataFrame. Estos nombres parecen ser códigos estándar utilizados en la representación de datos de encefalogramas **(EEG).**\n\nLista de Nombres Nuevos y Descriptivos: nombres_nuevos es una lista de **nombres más descriptivos para cada columna**. Estos nombres son más informativos y parecen reflejar la ubicación de los electrodos en un EEG, lo que podría ser **útil para una interpretación más clara de los datos.**\n\nEste paso es particularmente **útil en la preparación y análisis de datos, especialmente cuando se trabaja con conjuntos de datos complejos como los EEG**. Tener nombres de columnas descriptivos **facilita mucho la comprensión de los datos** ","metadata":{}},{"cell_type":"code","source":"# Nombres actuales de las columnas en el orden que proporcionaste\nnombres_actuales = [\n    'Fp1', 'F3', 'C3', 'P3', 'F7', 'T3', 'T5', 'O1', \n    'Fz', 'Cz', 'Pz', 'Fp2', 'F4', 'C4', 'P4', 'F8', \n    'T4', 'T6', 'O2', 'EKG'\n]\n\n# Nombres nuevos y descriptivos para cada columna\nnombres_nuevos = [\n    'Polo Frontal Izquierdo', 'Frontal Izquierdo', 'Central Izquierdo', 'Parietal Izquierdo', \n    'Fronto-Temporal Izquierdo', 'Temporal Izquierdo', 'Temporo-Occipital Izquierdo', 'Occipital Izquierdo',\n    'Línea Media Frontal', 'Línea Media Central', 'Línea Media Parietal', \n    'Polo Frontal Derecho', 'Frontal Derecho', 'Central Derecho', 'Parietal Derecho', \n    'Fronto-Temporal Derecho', 'Temporal Derecho', 'Temporo-Occipital Derecho', 'Occipital Derecho',\n    'Electrocardiograma'\n]\n\n# Renombrar las columnas del DataFrame\ndatos_combinados_1.columns = nombres_nuevos\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datos_combinados_1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Muestra de todos los histogrmas \n\n**Iteración Sobre las Columnas del DataFrame:** El bucle for columna in **datos_combinados_1.columns** recorre cada columna en datos_combinados_1. Para cada columna, se ejecutan una serie de comandos de visualización.\n\n**Creación de una Figura para Cada Histograma:**\n**plt.figure(figsize=(10, 6))** crea una nueva figura para cada histograma con un tamaño específico (10x6 pulgadas en este caso). **Es importante crear una nueva figura para cada columna para asegurarse de que los histogramas no se superpongan entre sí.**\n\n**Generación y Configuración del Histograma:**\n**datos_combinados_1[columna].hist(bins=20)** genera un histograma para la columna actual. Se especifican 20 \"bins\" o barras, lo cual determina cómo se agrupan los valores de los datos.\n\n**Activación de la Cuadrícula y Mostrar el Histograma:**\n**plt.grid(True)** activa la cuadrícula en el gráfico, lo que puede ayudar a **evaluar mejor** la escala y la distribución de los valores. **plt.show()** muestra la figura creada con el histograma.\n\nEste enfoque de visualización es **muy útil** en el análisis exploratorio de datos, ya que proporciona una **visión clara de la distribución de los valores en cada columna del DataFrame**. Al visualizar cada columna individualmente, puedes **identificar rápidamente patrones, anomalías y tendencias en tus datos**, lo cual es fundamental para comprender las características subyacentes del conjunto de datos y para tomar decisiones informadas en etapas posteriores del análisis o modelado.\n\n","metadata":{}},{"cell_type":"code","source":"# Suponiendo que datos_combinados_1 ya está cargado y contiene las columnas de interés\nfor columna in datos_combinados_1.columns:\n    plt.figure(figsize=(10, 6))  # Ajusta el tamaño de la figura si es necesario\n    datos_combinados_1[columna].hist(bins=20)  # Ajusta el número de bins según tus necesidades\n    plt.title(f'Distribución de Valores en {columna}')\n    plt.xlabel(columna)\n    plt.ylabel('Frecuencia')\n    plt.grid(True)\n    plt.show()\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Captura del tiempo final.","metadata":{}},{"cell_type":"code","source":"tiempo_final = time.time()\ntiempo_total =  tiempo_final - tiempo_inicial\nprint('El tiempo total del cuaderno ha sido de:' , tiempo_total / 60,'Minutos')","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}