# Cargar las librerías necesarias
library(readxl)
library(dplyr)
## 
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)

# 1. Introducción
# En este análisis exploraremos un conjunto de datos relacionado con algoritmos de inteligencia artificial (IA) y su rendimiento utilizando frameworks como Scikit-learn y Keras. 
# El objetivo es responder la pregunta:
# ¿Cuál es el algoritmo de inteligencia artificial que ofrece el mejor equilibrio entre precisión y tiempo de entrenamiento para problemas de clustering utilizando el framework Keras?

# 2. Importación de los Datos
# Importar el conjunto de datos
dataset <- read_excel("C:/Users/USER/Documents/NUEVO EDA EST/Dataset_IA_corte_II.xlsx")

# Mostrar las primeras filas del conjunto de datos
head(dataset)
## # A tibble: 6 × 10
##   Algorithm      Framework   Problem_Type Dataset_Type Accuracy Precision Recall
##   <chr>          <chr>       <chr>        <chr>           <dbl>     <dbl>  <dbl>
## 1 SVM            Scikit-lea… Regression   Time Series     0.662     0.693 NA    
## 2 K-Means        Keras       Clustering   Time Series     0.744     0.490  0.877
## 3 Neural Network Keras       Clustering   Image           0.885     0.595  0.969
## 4 SVM            Keras       Clustering   Text            0.842     0.842  0.875
## 5 SVM            Scikit-lea… Regression   Tabular         0.723     0.686  0.301
## 6 K-Means        PyTorch     Regression   Image           0.637     0.626  7.45 
## # ℹ 3 more variables: F1_Score <dbl>, Training_Time <dbl>, Date <dttm>
# Estructura del dataset
str(dataset)
## tibble [560 × 10] (S3: tbl_df/tbl/data.frame)
##  $ Algorithm    : chr [1:560] "SVM" "K-Means" "Neural Network" "SVM" ...
##  $ Framework    : chr [1:560] "Scikit-learn" "Keras" "Keras" "Keras" ...
##  $ Problem_Type : chr [1:560] "Regression" "Clustering" "Clustering" "Clustering" ...
##  $ Dataset_Type : chr [1:560] "Time Series" "Time Series" "Image" "Text" ...
##  $ Accuracy     : num [1:560] 0.662 0.744 0.885 0.842 0.723 ...
##  $ Precision    : num [1:560] 0.693 0.49 0.595 0.842 0.686 ...
##  $ Recall       : num [1:560] NA 0.877 0.969 0.875 0.301 ...
##  $ F1_Score     : num [1:560] 0.443 0.441 0.964 0.704 0.646 ...
##  $ Training_Time: num [1:560] 4.98 NA 3.28 4.04 3.6 ...
##  $ Date         : POSIXct[1:560], format: "2023-03-08 11:26:21" "2023-03-09 11:26:21" ...
# 3. Limpieza, tratamiento y preparación
# Verificación de valores faltantes
missing_values <- sapply(dataset, function(x) sum(is.na(x)))
missing_values
##     Algorithm     Framework  Problem_Type  Dataset_Type      Accuracy 
##             0             0             0             0            39 
##     Precision        Recall      F1_Score Training_Time          Date 
##            19            20            20            20             0
# Eliminación de filas con valores faltantes
dataset_clean <- dataset %>% na.omit()

# Verificar que no queden más valores faltantes
sapply(dataset_clean, function(x) sum(is.na(x)))
##     Algorithm     Framework  Problem_Type  Dataset_Type      Accuracy 
##             0             0             0             0             0 
##     Precision        Recall      F1_Score Training_Time          Date 
##             0             0             0             0             0
# Resumen estadístico de las variables numéricas
summary(select_if(dataset_clean, is.numeric))
##     Accuracy        Precision          Recall          F1_Score     
##  Min.   :0.5038   Min.   :0.4031   Min.   :0.3001   Min.   :0.4000  
##  1st Qu.:0.6183   1st Qu.:0.5661   1st Qu.:0.4898   1st Qu.:0.5486  
##  Median :0.7490   Median :0.7275   Median :0.6513   Median :0.7031  
##  Mean   :0.8458   Mean   :0.8387   Mean   :0.7611   Mean   :0.8014  
##  3rd Qu.:0.8698   3rd Qu.:0.8670   3rd Qu.:0.8365   3rd Qu.:0.8396  
##  Max.   :9.7181   Max.   :9.7320   Max.   :9.3662   Max.   :9.3740  
##  Training_Time    
##  Min.   : 0.1032  
##  1st Qu.: 1.2982  
##  Median : 2.4809  
##  Mean   : 3.0598  
##  3rd Qu.: 3.8446  
##  Max.   :46.9856
# Detección de outliers en la columna Accuracy utilizando el método IQR
Q1 <- quantile(dataset_clean$Accuracy, 0.25, na.rm = TRUE)
Q3 <- quantile(dataset_clean$Accuracy, 0.75, na.rm = TRUE)
IQR <- Q3 - Q1

# Definición de los límites superior e inferior
lower_bound <- Q1 - 1.5 * IQR
upper_bound <- Q3 + 1.5 * IQR

# Winsorización: ajustar los valores por fuera de los límites a los límites
dataset_clean$Accuracy <- ifelse(dataset_clean$Accuracy < lower_bound, lower_bound, dataset_clean$Accuracy)
dataset_clean$Accuracy <- ifelse(dataset_clean$Accuracy > upper_bound, upper_bound, dataset_clean$Accuracy)

# Cálculo del IQR para Training_Time
Q1_time <- quantile(dataset_clean$Training_Time, 0.25, na.rm = TRUE)
Q3_time <- quantile(dataset_clean$Training_Time, 0.75, na.rm = TRUE)
IQR_time <- Q3_time - Q1_time

# Definir los límites para detectar outliers en Training_Time
lower_bound_time <- Q1_time - 1.5 * IQR_time
upper_bound_time <- Q3_time + 1.5 * IQR_time

#Ajustar valores fuera de los límites a los límites
dataset_clean$Training_Time <- ifelse(
  dataset_clean$Training_Time < lower_bound_time, 
  lower_bound_time, 
  dataset_clean$Training_Time
)

dataset_clean$Training_Time <- ifelse(
  dataset_clean$Training_Time > upper_bound_time, 
  upper_bound_time, 
  dataset_clean$Training_Time
)

# 4. Análisis Descriptivo de las Variables
# Filtrar los datos para incluir solo problemas de Clustering con el framework Keras
dataset_clustering_keras <- dataset_clean %>%
  filter(Problem_Type == "Clustering", Framework == "Keras")

# Resumen estadístico de Accuracy y Training_Time
summary(select(dataset_clustering_keras, Accuracy, Training_Time))
##     Accuracy      Training_Time   
##  Min.   :0.5128   Min.   :0.2162  
##  1st Qu.:0.6231   1st Qu.:2.0985  
##  Median :0.7671   Median :3.3348  
##  Mean   :0.7388   Mean   :2.9899  
##  3rd Qu.:0.8429   3rd Qu.:3.9172  
##  Max.   :0.9850   Max.   :7.6641
# Visualización de Accuracy
ggplot(dataset_clustering_keras, aes(x = Accuracy)) +
  geom_histogram(bins = 30, fill = "blue", alpha = 0.7) +
  theme_minimal() +
  ggtitle("Distribución de Accuracy para problemas de Clustering con Keras")

# Análisis de la gráfica de Accuracy:
# En este gráfico, podemos ver que la mayoría de los valores de Accuracy están distribuidos entre 0.5 y 0.9. 
# Hay algunos valores atípicos cercanos a 1.0, lo que sugiere que ciertos algoritmos tienen una alta precisión.

# Visualización de Training_Time
ggplot(dataset_clustering_keras, aes(x = Training_Time)) +
  geom_histogram(bins = 30, fill = "green", alpha = 0.7) +
  theme_minimal() +
  ggtitle("Distribución de Training Time para problemas de Clustering con Keras")

# Análisis de la gráfica de Training_Time:
# La mayoría de los tiempos de entrenamiento están concentrados por debajo de 5 unidades de tiempo. 
# Sin embargo, hay algunos valores más altos, lo que indica que algunos algoritmos requieren más tiempo para completar el entrenamiento.

# Distribución de Algoritmos Utilizados en Clustering con Keras
# Tabla de frecuencias de Algorithm
table(dataset_clustering_keras$Algorithm)
## 
##        K-Means Neural Network  Random Forest            SVM 
##             16              9              8             11
# Gráfico de barras de Algorithm
ggplot(dataset_clustering_keras, aes(x = Algorithm)) +
  geom_bar(fill = "purple", alpha = 0.7) +
  theme_minimal() +
  ggtitle("Distribución de Algoritmos para problemas de Clustering con Keras")

# Análisis de la gráfica de Algoritmos:
# El gráfico muestra la frecuencia de cada algoritmo en problemas de Clustering. 
# Podemos observar que K-Means es el más utilizado, seguido de Neural Network.

# 5. Análisis Bivariado
# Comparación de Accuracy por Algorithm
ggplot(dataset_clustering_keras, aes(x = Algorithm, y = Accuracy, fill = Algorithm)) +
  geom_boxplot(alpha = 0.7) +
  theme_minimal() +
  ggtitle("Comparación de Accuracy por Algoritmo (Clustering con Keras)")

# Análisis de la gráfica de Accuracy por Algoritmo:
# Esta gráfica muestra que Random Forest tiene la mayor mediana de precisión, mientras que Neural Network tiene una precisión más baja. 


# Comparación de Training Time por Algorithm
ggplot(dataset_clustering_keras, aes(x = Algorithm, y = Training_Time, fill = Algorithm)) +
  geom_boxplot(alpha = 0.7) +
  theme_minimal() +
  ggtitle("Comparación de Training Time por Algoritmo (Clustering con Keras)")

# Análisis de la gráfica de Training Time por Algoritmo:
# Aquí podemos ver que SVM tiene el menor tiempo de entrenamiento en promedio, mientras que Neural Network tiene tiempos más largos.
# Sin embargo, hay mucha variabilidad en los tiempos de entrenamiento para Neural Network.

# 6. Conclusiones
# 1) El algoritmo Random Forest presenta la mayor precisión promedio entre los algoritmos evaluados.
# 2) SVM es el algoritmo con el menor tiempo de entrenamiento en promedio, aunque Neural Network presenta tiempos más largos pero menor precisión.
# 3) Si se busca máxima precisión, el algoritmo Random Forest es la mejor opción.
# 4) Para un equilibrio entre precisión razonable y menor tiempo de entrenamiento, SVM ofrece un buen compromiso.

# En conclusión, el algoritmo de inteligencia artificial que ofrece el mejor equilibrio entre precisión y tiempo de entrenamiento para problemas de clustering utilizando Keras es SVM, ya que su tiempo de entrenamiento es considerablemente más corto, lo que lo hace eficiente en escenarios donde el tiempo de ejecución es una prioridad.