Tabla Descriptiva de los datos

Matrices de correlación

Se mostrarán las matrices obtenidas de los distintos tipos de correlaciones encontradas.

Es importante aclarar los datos que se están revisando; a continuación se explicarán los formatos de los datos a ver:

Correlación de Spearman

corrplot(
  correlación_1,
  method = "color",
  bg = "gray",
  type = "upper",
  title = "Matriz Correlación Spearman",
  tl.cex = 0.9,
  outline = TRUE,
  tl.srt = 45,
  tl.offset = 0.9,
  tl.pos = "lt",
  tl.col = "Black",
  addCoef.col = "black",
  number.cex = 0.7,
  mar = c(1,1,2.5,1)
)

Correlación de Pearson

corrplot(
  correlación_2,
  method = "color",
  bg = "gray",
  type = "upper",
  title = "Matriz Correlación pearson",
  tl.cex = 0.9,
  outline = TRUE,
  tl.srt = 45,
  tl.offset = 0.9,
  tl.pos = "lt",
  tl.col = "Black",
  addCoef.col = "black",
  number.cex = 0.7,
  mar = c(1,1,2.5,1)
)

Correlación de Kendall

corrplot(
  correlación_3,
  method = "color",
  bg = "gray",
  type = "upper",
  title = "Matriz Correlación Kendall",
  tl.cex = 0.9,
  outline = TRUE,
  tl.srt = 45,
  tl.offset = 0.9,
  tl.pos = "lt",
  tl.col = "Black",
  addCoef.col = "black",
  number.cex = 0.7,
  mar = c(1,1,2.5,1)
)

Matrices de correlación según carreras

Carrera de Doctorado

for (m in names(matrices_carreras[["doctorado"]])) {
  corrplot(
  matrices_carreras[["doctorado"]][[m]],
  method = "color",
  bg = "gray",
  type = "upper",
  title = paste0("Matriz Correlación ", m),
  tl.cex = 0.9,
  outline = TRUE,
  tl.srt = 45,
  tl.offset = 0.9,
  tl.pos = "lt",
  tl.col = "Black",
  addCoef.col = "black",
  number.cex = 0.7,
  mar = c(1,1,2.5,1)
)
}

Carrera de Doctorado en ciencias

for (m in names(matrices_carreras[["doctorado en ciencias de la ingenieria con mencion en informatica"]])) {
  corrplot(
  matrices_carreras[["doctorado en ciencias de la ingenieria con mencion en informatica"]][[m]],
  method = "color",
  bg = "gray",
  type = "upper",
  title = paste0("Matriz Correlación ", m),
  tl.cex = 0.9,
  outline = TRUE,
  tl.srt = 45,
  tl.offset = 0.9,
  tl.pos = "lt",
  tl.col = "Black",
  addCoef.col = "black",
  number.cex = 0.7,
  mar = c(1,1,2.5,1)
)
}

Carrera de ingeniería civil en biomedica

for (m in names(matrices_carreras[["ingenieria civil en biomedica"]])) {
  corrplot(
  matrices_carreras[["ingenieria civil en biomedica"]][[m]],
  method = "color",
  bg = "gray",
  type = "upper",
  title = paste0("Matriz Correlación ", m),
  tl.cex = 0.9,
  outline = TRUE,
  tl.srt = 45,
  tl.offset = 0.9,
  tl.pos = "lt",
  tl.col = "Black",
  addCoef.col = "black",
  number.cex = 0.7,
  mar = c(1,1,2.5,1)
)
}

Carrera de ingeniería civil en informática

for (m in names(matrices_carreras[["ingenieria civil en informatica"]])) {
  corrplot(
  matrices_carreras[["ingenieria civil en informatica"]][[m]],
  method = "color",
  bg = "gray",
  type = "upper",
  title = paste0("Matriz Correlación ", m),
  tl.cex = 0.9,
  outline = TRUE,
  tl.srt = 45,
  tl.offset = 0.9,
  tl.pos = "lt",
  tl.col = "Black",
  addCoef.col = "black",
  number.cex = 0.7,
  mar = c(1,1,2.5,1)
)
}

Carrera de ingeniería de ejecución en computación e informática

for (m in names(matrices_carreras[["ingenieria de ejecucion en computacion e informatica"]])) {
  corrplot(
  matrices_carreras[["ingenieria de ejecucion en computacion e informatica"]][[m]],
  method = "color",
  bg = "gray",
  type = "upper",
  title = paste0("Matriz Correlación ", m),
  tl.cex = 0.9,
  outline = TRUE,
  tl.srt = 45,
  tl.offset = 0.9,
  tl.pos = "lt",
  tl.col = "Black",
  addCoef.col = "black",
  number.cex = 0.7,
  mar = c(1,1,2.5,1)
)
}

Carrera de ingeniería ejecución en minas

for (m in names(matrices_carreras[["ingenieria ejecucion en minas"]])) {
  corrplot(
  matrices_carreras[["ingenieria ejecucion en minas"]][[m]],
  method = "color",
  bg = "gray",
  type = "upper",
  title = paste0("Matriz Correlación ", m),
  tl.cex = 0.9,
  outline = TRUE,
  tl.srt = 45,
  tl.offset = 0.9,
  tl.pos = "lt",
  tl.col = "Black",
  addCoef.col = "black",
  number.cex = 0.7,
  mar = c(1,1,2.5,1)
)
}

Carrera de magister en ingeniería informática

for (m in names(matrices_carreras[["magister en ingenieria informatica"]])) {
  corrplot(
  matrices_carreras[["magister en ingenieria informatica"]][[m]],
  method = "color",
  bg = "gray",
  type = "upper",
  title = paste0("Matriz Correlación ", m),
  tl.cex = 0.9,
  outline = TRUE,
  tl.srt = 45,
  tl.offset = 0.9,
  tl.pos = "lt",
  tl.col = "Black",
  addCoef.col = "black",
  number.cex = 0.7,
  mar = c(1,1,2.5,1)
)
}

Depuración de la base de datos

Durante la revisión de la base de datos se detectó una inconsistencia en el valor de los créditos SCT-Chile asignados a las asignaturas pertenecientes al programa de Doctorado.

Como parte del proceso de depuración, se actualizó el valor de estas asignaturas, modificándolo de 5 a 6 créditos SCT-Chile, con el fin de mantener la consistencia de la información utilizada durante el análisis.

El caso de Magister

Durante la revisión de las matrices de correlación se identificó que la carrera Magíster en Ingeniería Informática presentaba una cantidad insuficiente de datos para generar resultados representativos.

Al revisar la base de datos se encontró que esta carrera estaba representada por un único estudiante. Además, se detectó la ausencia de la nota final de la siguiente asignatura:

También se verificó que el estudiante no completó la bitácora, por lo que no se dispone de información sobre las horas dedicadas a las asignaturas cursadas. Como consecuencia, no fue posible generar la información correspondiente a la Carga Académica Declarada (Bitácora) para este caso.

Caso similares

A partir del análisis realizado sobre la carrera Magíster en Ingeniería Informática, se revisaron otras carreras que también presentaban inconsistencias en sus matrices de correlación, específicamente Doctorado y Doctorado en Ciencias.

La revisión permitió identificar que ambas carreras también estaban representadas por un único estudiante. Adicionalmente, en la carrera Doctorado en Ciencias se detectó la ausencia de la nota final de la siguiente asignatura:

  • Seminario de Tesis 1.

A diferencia del caso del Magíster, los estudiantes de estas carreras sí completaron la bitácora. Por ello, se dispone de la información correspondiente a la Carga Académica Declarada (Bitácora), permitiendo realizar el procesamiento de dicha variable. En consecuencia, el impacto de la información faltante sobre el análisis de las matrices de correlación es menor en comparación con el caso del Magíster.

Modelamiento

Una vez generadas las matrices de correlación correspondientes a las distintas cargas académicas (efectiva, declarada, percibida y notas), se inició la etapa de modelamiento. En esta etapa se definieron las variables dependientes y las variables predictoras que serían utilizadas durante el entrenamiento de los modelos.

Variables dependientes

Las variables dependientes corresponden a los valores sobre los cuales se busca realizar las predicciones y el análisis. Para esta investigación se seleccionaron las siguientes variables:

  • Nota.

  • Carga Académica Efectiva.

  • Carga Académica Declarada (Encuesta).

  • Carga Académica Declarada (Bitácora).

  • Carga Académica Percibida.

Estas variables representan los principales indicadores analizados durante la investigación y constituyen los objetivos de predicción de los distintos modelos desarrollados.

Variables predictoras

Las variables predictoras corresponden a la información utilizada para explicar o predecir el comportamiento de las variables dependientes.

Para su selección se utilizaron las respuestas obtenidas en la encuesta aplicada a los estudiantes. Estas variables representan distintos aspectos personales, académicos y contextuales que pueden influir tanto en el rendimiento académico como en la percepción de la carga académica.

Debido a que las respuestas de la encuesta presentan distintos formatos, fue necesario realizar un proceso de transformación para adecuarlas al entrenamiento de los modelos. Las variables predictoras se clasificaron según el tipo de dato original.

Escala Likert

Las preguntas con respuestas en escala Likert fueron transformadas a valores numéricos utilizando su escala ordinal, asignando valores desde 1 (Muy en desacuerdo) hasta 5 (Muy de acuerdo).

Las variables consideradas fueron:

  • Semestre_Abrumador

  • Tiempo_Insuficiente

  • Estrés_Percibido

  • Dificultad_Percibida_Encuesta

  • Importancia_Percibida_Encuesta

  • Motivación_Percibida_Encuesta

  • Dedicación_Rendimiento_Encuesta

Variables binarias

Las preguntas respondidas mediante opciones Sí/No fueron transformadas a una representación binaria, asignando el valor 1 para la respuesta y 0 para la respuesta No.

La variable utilizada fue:

  • Factor_Salud

Variables categóricas

Algunas preguntas de la encuesta contenían múltiples categorías sin un orden natural, por lo que no era apropiado representarlas mediante una escala numérica.

Para estas variables se aplicó una codificación mediante variables dummy (One-Hot Encoding), generando una columna binaria para cada categoría presente en la base de datos. Cada columna indica la presencia o ausencia de una categoría determinada para cada estudiante.

Las variables transformadas mediante este procedimiento fueron:

  • Factor_Viaje

  • Factor_Responsabilidad

  • Factor_Financiamiento

  • Factor_Establecimiento_Escolar

  • Asignatura

  • Carrera

Métricas de calidad y validación cruzada

Una vez clasificadas las variables predictoras, se realizó una revisión de las variables dependientes con el objetivo de determinar el tipo de problema de aprendizaje automático a resolver. Esta clasificación permite seleccionar los algoritmos compatibles con la naturaleza de los datos.

Las variables dependientes fueron clasificadas de la siguiente manera:

Al tratarse de variables continuas, todas las predicciones corresponden a un problema de regresión, permitiendo utilizar el mismo conjunto de algoritmos para evaluar cada una de las variables dependientes.

Selección de algoritmos

Considerando que todas las variables objetivo corresponden a un problema de regresión, se seleccionó un conjunto de algoritmos capaces de realizar este tipo de predicciones. Aunque todos persiguen el mismo objetivo, cada uno emplea una metodología distinta para aprender los patrones presentes en los datos, por lo que su desempeño puede variar dependiendo de la información disponible.

La investigación utiliza la Regresión Lineal como modelo de referencia. No obstante, también se entrenan otros algoritmos con el propósito de comparar su desempeño e identificar cuál presenta una mejor capacidad predictiva para cada una de las variables dependientes.

Los algoritmos utilizados fueron los siguientes:

Validación cruzada

Una vez definidos los algoritmos, se estableció el método de entrenamiento y evaluación de los modelos.

En lugar de entrenar cada algoritmo utilizando una única división de la base de datos, se optó por emplear validación cruzada de 10 particiones (10-Fold Cross Validation) mediante el método Cross Validation (cv) disponible en la librería caret.

Durante este procedimiento, la base de datos se divide en diez subconjuntos de tamaño similar. En cada iteración, uno de estos subconjuntos se utiliza para evaluar el modelo, mientras que los nueve restantes son utilizados para entrenarlo. El proceso se repite diez veces, permitiendo que cada subconjunto sea utilizado una vez como conjunto de evaluación.

Este procedimiento proporciona una estimación más estable del rendimiento del modelo y reduce la dependencia de una única partición de entrenamiento y prueba, permitiendo comparar los algoritmos de manera más confiable.

El entrenamiento de cada algoritmo se realizó mediante la siguiente función:

evaluar_modelo <- function(datos, objetivo, metodo){
  
  control <- trainControl(
    method = "cv",
    number = 10
  )
  modelo <- tryCatch(
    train(
      as.formula(paste(objetivo,"~ .")),
      data = datos,
      method = metodo,
      trControl = control,
      na.action = na.omit
    ),
    error = function(e) return(NULL)
  )
  if(is.null(modelo)){
    return(
      list(
        metodo = metodo,
        algoritmo = modelo,
        datos = datos,
        objetivo = objetivo,
        metricas = data.frame(
          Metodo = metodo,
          RMSE=NA,
          MAE=NA,
          R2=NA
        )
      )
    )
  }
  
  list(
    # Cual es el metodo que se utilizo
    metodo = metodo,
    # Cual fue el entrenamiento
    algoritmo = modelo,
    # Los datos utilizados
    datos = datos,
    # Cual es el objetivo que se esta estudiando
    objetivo = objetivo,
    # Tabla con las metricas a comparar
    metricas = data.frame(
      Metodo = metodo,
      RMSE = min(modelo$results$RMSE, na.rm = TRUE),
      MAE = min(modelo$results$MAE, na.rm = TRUE),
      R2 = max(modelo$results$Rsquared, na.rm = TRUE)
    )
  )
}

Esta función recibe como parámetros la base de datos, la variable dependiente y el algoritmo a entrenar. Como resultado devuelve:

Métricas de evaluación

Para comparar el desempeño de los distintos algoritmos se utilizaron tres métricas ampliamente empleadas en problemas de regresión:

Estas métricas permiten comparar objetivamente el rendimiento de cada algoritmo y seleccionar aquellos que presentan un mejor equilibrio entre precisión y capacidad de generalización.

Posteriormente se presenta una tabla con los resultados obtenidos para cada variable dependiente, permitiendo comparar el desempeño de todos los algoritmos evaluados.

Tratamiento de valores faltantes

Algunos de los algoritmos utilizados no admiten valores faltantes (NA) en la variable dependiente durante el entrenamiento. Sin embargo, debido a las características de la base de datos, existen registros que presentan información incompleta, principalmente por la ausencia de notas finales o de datos asociados a determinadas asignaturas.

Con el fin de mantener la compatibilidad entre todos los algoritmos evaluados, se optó por eliminar únicamente aquellas filas que presentaban valores faltantes en la variable dependiente correspondiente al momento del entrenamiento (na.omit).

Este procedimiento se realiza de manera independiente para cada variable objetivo, por lo que la cantidad de registros utilizados puede variar entre los distintos modelos. Para mantener la transparencia del proceso, se informa la cantidad de registros eliminados en cada uno de los entrenamientos realizados.

Nota

Se eliminaron 10 notas.

library("knitr")
library("kableExtra")

kable(
  head(Lista_Tablas$Com_Tab_Nota, 20),
  caption = "Tabla de Notas"
) |>
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width = TRUE
  )
Tabla de Notas
Metodo RMSE MAE R2
lm 0.6471644 0.3661054 0.0448047
glmnet 0.5059043 0.2312156 0.0645936
rpart 0.4639463 0.2024861 0.0501960
rf 0.4630184 0.1970010 0.0882746
xgbTree NA NA NA
svmRadial 0.4543691 0.2014593 0.1366084
ridge NA NA NA
pls 0.4483394 0.2485984 0.0746307
pcr 0.4519940 0.1959415 0.1268392
knn 0.4867570 0.2367081 0.1582762
ranger 0.4703668 0.1952023 0.0956885
gbm 0.4704499 0.2532254 0.1123164
cubist 0.4787467 0.1600484 0.1366327
earth 0.4919261 0.2038445 0.0746425

Efectiva

Se elimino una fila de carga académica efectiva.

kable(
  head(Lista_Tablas$Com_Tab_Efectiva, 20),
  caption = "Tabla de Carga Académica Efectiva"
) |>
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width = TRUE
  )
Tabla de Carga Académica Efectiva
Metodo RMSE MAE R2
lm 0.4236779 0.1678555 0.7755966
glmnet 0.3227928 0.1067959 0.8617829
rpart 0.9299730 0.7087823 0.2274891
rf 0.4121754 0.1859316 0.8220922
xgbTree NA NA NA
svmRadial 0.7295604 0.5162592 0.5506068
ridge NA NA NA
pls 0.8431132 0.6573779 0.3391804
pcr 0.8974459 0.7086590 0.2436685
knn 0.8361809 0.6337469 0.3541130
ranger 0.3738134 0.1523287 0.8564130
gbm 0.8441662 0.6344221 0.3244794
cubist 0.5542899 0.2518966 0.6684926
earth 0.3998427 0.1229932 0.8237865

Declarada Encuesta

Se elimino 0 filas de carga académica declarada en la encuesta

kable(
  head(Lista_Tablas$Com_Tab_Declarada_E, 20),
  caption = "Tabla de Carga Académica Declarada Encuesta"
) |>
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width = TRUE
  )
Tabla de Carga Académica Declarada Encuesta
Metodo RMSE MAE R2
lm 0.0852131 0.0645902 0.4156717
glmnet 0.0786532 0.0574542 0.4360940
rpart 0.0954938 0.0737944 0.1816182
rf 0.0793624 0.0590910 0.4247540
xgbTree NA NA NA
svmRadial 0.0896631 0.0728936 0.3644732
ridge NA NA NA
pls 0.0837590 0.0634804 0.3535514
pcr 0.0847888 0.0642105 0.3311910
knn 0.0861589 0.0649351 0.3186146
ranger 0.0792582 0.0590531 0.4049881
gbm 0.0821535 0.0619444 0.3736460
cubist 0.0786803 0.0591293 0.4480401
earth 0.0800333 0.0599036 0.4342293

Declarada Bitácora

Se elimino 65 filas de carga académica declarada en la bitácora

kable(
  head(Lista_Tablas$Com_Tab_Declarada_B, 20),
  caption = "Tabla de Carga Académica Declarada Bitacora"
) |>
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width = TRUE
  )
Tabla de Carga Académica Declarada Bitacora
Metodo RMSE MAE R2
lm 31.77861 22.90597 0.4531566
glmnet 31.27627 22.92211 0.4632307
rpart 38.25211 28.20788 0.1684893
rf 31.68838 22.71041 0.4600344
xgbTree NA NA NA
svmRadial 40.98433 28.83382 0.2836301
ridge NA NA NA
pls 35.01606 26.65389 0.2908438
pcr 35.26449 27.32804 0.2777318
knn 34.91214 25.96187 0.3046772
ranger 31.84264 22.70350 0.4382106
gbm 32.31847 24.12983 0.3885667
cubist 31.00428 22.53089 0.4502663
earth 33.37375 24.61509 0.3988331

Percibida

Se elimino 1 fila de carga académica percibida

kable(
  head(Lista_Tablas$Com_Tab_Percibida, 20),
  caption = "Tabla de Carga Académica Percibida"
) |>
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed"),
    full_width = TRUE
  )
Tabla de Carga Académica Percibida
Metodo RMSE MAE R2
lm 1.1120442 0.8681505 0.4930488
glmnet 0.9712083 0.7779195 0.5561411
rpart 1.0888917 0.8640222 0.4479062
rf 0.9794344 0.7597044 0.5629289
xgbTree NA NA NA
svmRadial 0.9666431 0.7037720 0.5689860
ridge NA NA NA
pls 0.9733001 0.7460939 0.5781811
pcr 1.0081140 0.7968719 0.5275092
knn 0.9996692 0.7967619 0.5424369
ranger 0.9679965 0.7549786 0.5681578
gbm 0.9791138 0.7773315 0.5551124
cubist 0.9778553 0.7445140 0.5649743
earth 1.0564541 0.8232510 0.4911562

Durante el procesamiento de los datos se observó que algunos algoritmos no lograron completar correctamente su entrenamiento, entregando valores vacíos (NA) en las métricas de evaluación.

Tras revisar los mensajes de error generados durante la ejecución, se determinó que estos algoritmos presentaban problemas de compatibilidad con la configuración del entorno de trabajo o con las librerías utilizadas para su implementación. Debido a ello, no fue posible obtener métricas de calidad comparables con el resto de los modelos.

En consecuencia, estos algoritmos fueron excluidos del análisis comparativo y únicamente se consideraron aquellos que completaron satisfactoriamente el proceso de entrenamiento y evaluación.

Gráficos de Importancia y SHAP

Una vez entrenados y evaluados los modelos, es posible conocer su capacidad predictiva mediante las métricas de calidad. Sin embargo, estas métricas no permiten identificar cuáles son las variables que más influyen en las predicciones ni la forma en que contribuyen al resultado obtenido.

Con el objetivo de interpretar el comportamiento de los modelos se utilizaron dos herramientas de interpretabilidad: Importancia de Variables (Permutation Feature Importance) y SHAP (SHapley Additive exPlanations).

El gráfico de Importancia permite identificar cuáles son las variables más relevantes para el modelo. Para ello, se mide la pérdida de desempeño (Dropout Loss) al alterar aleatoriamente los valores de cada variable. Mientras mayor sea la pérdida de desempeño, mayor es la importancia de dicha variable para el modelo. Este análisis corresponde a una interpretación global, ya que considera el comportamiento del modelo sobre toda la base de datos.

Por otra parte, SHAP permite explicar una predicción individual. Este método cuantifica la contribución de cada variable al resultado obtenido por el modelo, indicando tanto la magnitud como la dirección de su efecto. Un valor SHAP positivo representa una contribución que incrementa la predicción, mientras que un valor negativo indica que la reduce.

Para obtener ambos análisis se implementó la siguiente función:

explicar_modelo <- function(resultados, fila = 1, top = 10){
  datos <- na.omit(resultados$datos)
  
  x <- datos[, !(names(resultados$datos) %in% resultados$objetivo)]
  y <- datos[[resultados$objetivo]]
  
  explainer <- explain(
    model = resultados$algoritmo,
    data = x,
    y = y,
    label = resultados$metodo,
    verbose = FALSE
  )
  
  ### ### ### ###
  # Importancia #
  ### ### ### ###
  
  mp <- model_parts(
    explainer,
    type = "raw"
  )
  
  mp_plot <- mp |>
    dplyr::filter(
      !variable %in% c("_baseline_", "_full_model_")
    ) |>
    dplyr::group_by(variable) |>
    dplyr::summarise(
      dropout_loss = mean(dropout_loss),
      .groups = "drop"
    ) |>
    dplyr::slice_max(
      order_by = dropout_loss,
      n = top
    )
  
  grafico_mp <- ggplot(
    mp_plot,
    aes(reorder(variable, dropout_loss),dropout_loss)) +
    geom_col() +
    coord_flip() +
    labs( x = "", y = "Importancia (Dropout Loss)" , title = "Grafica de Importancia")
  
  ## ## ##
  # SHAP #
  ## ## ##
  
  shap <- predict_parts(
    explainer,
    new_observation = x[fila, ],
    type = "shap"
  )
  
  grafico_shap <- plot(shap)
  print(plot(shap))
  
  ## ## ## ## 
  # entrega #
  ## ## ## ##
  
  list(
    importancia = mp,
    shap = shap,
    grafico_mp = grafico_mp,
    grafico_shad = grafico_shap
  )
}

La función recibe como entrada el resultado del entrenamiento de un modelo y realiza los siguientes pasos:

Para calcular los valores SHAP es necesario seleccionar una observación de la base de datos. En esta investigación se utilizó, como ejemplo, la primera observación disponible (fila = 1). La elección de esta fila tiene únicamente fines de interpretación y visualización del comportamiento del modelo.

En las siguientes secciones se presentan los gráficos de importancia y SHAP obtenidos para los modelos seleccionados, permitiendo identificar las variables más relevantes y analizar cómo cada una de ellas contribuye a las predicciones realizadas.

Notas

LM

library(plotly)
## 
## Adjuntando el paquete: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
p1 <- ggplotly(Graficos$Nota_Lm.grafico_mp) %>%
        layout(dragmode = "zoom",
                   xaxis = list(
                     title = list(
                       text = "Importancia",
                       standoff = 5)
                     )
               )

p2 <- ggplotly(Graficos$Nota_Lm.grafico_shad) %>%
        layout(dragmode = "zoom",
               xaxis = list(
                 title = list(
                   text = "Contribución",
                   standoff = 5)))

subplot(
  p1,
  p2,
  nrows = 2,
  titleX = TRUE,
  titleY = TRUE,
  margin = 0.10,
  heights = c(0.40, 0.60)
)

Gbm

p1 <- ggplotly(Graficos$Nota_Gbm.grafico_mp) %>%
        layout(dragmode = "zoom",
                   xaxis = list(
                     title = list(
                       text = "Importancia",
                       standoff = 5)
                     )
               )

p2 <- ggplotly(Graficos$Nota_Gbm.grafico_shad) %>%
        layout(dragmode = "zoom",
               xaxis = list(
                 title = list(
                   text = "Contribución",
                   standoff = 5)))

subplot(
  p1,
  p2,
  nrows = 2,
  titleX = TRUE,
  titleY = TRUE,
  margin = 0.10,
  heights = c(0.40, 0.60)
)

Carga Académica Declarada Encuesta

Lm

library(plotly)

p1 <- ggplotly(Graficos$DeclaradaE_lm.grafico_mp) %>%
        layout(dragmode = "zoom",
                   xaxis = list(
                     title = list(
                       text = "Importancia",
                       standoff = 5)
                     )
               )

p2 <- ggplotly(Graficos$DeclaradaE_lm.grafico_shad) %>%
        layout(dragmode = "zoom",
               xaxis = list(
                 title = list(
                   text = "Contribución",
                   standoff = 5)))

subplot(
  p1,
  p2,
  nrows = 2,
  titleX = TRUE,
  titleY = TRUE,
  margin = 0.10,
  heights = c(0.40, 0.60)
)

Knn

library(plotly)

p1 <- ggplotly(Graficos$DeclaradaE_knn.grafico_mp) %>%
        layout(dragmode = "zoom",
                   xaxis = list(
                     title = list(
                       text = "Importancia",
                       standoff = 5)
                     )
               )

p2 <- ggplotly(Graficos$DeclaradaE_knn.grafico_shad) %>%
        layout(dragmode = "zoom",
               xaxis = list(
                 title = list(
                   text = "Contribución",
                   standoff = 5)))

subplot(
  p1,
  p2,
  nrows = 2,
  titleX = TRUE,
  titleY = TRUE,
  margin = 0.10,
  heights = c(0.40, 0.60)
)

Carga Académica Declarada Bitácora

Lm

library(plotly)

p1 <- ggplotly(Graficos$DeclaradaB_lm.grafico_mp) %>%
        layout(dragmode = "zoom",
                   xaxis = list(
                     title = list(
                       text = "Importancia",
                       standoff = 5)
                     )
               )

p2 <- ggplotly(Graficos$DeclaradaB_lm.grafico_shad) %>%
        layout(dragmode = "zoom",
               xaxis = list(
                 title = list(
                   text = "Contribución",
                   standoff = 5)))

subplot(
  p1,
  p2,
  nrows = 2,
  titleX = TRUE,
  titleY = TRUE,
  margin = 0.10,
  heights = c(0.40, 0.60)
)

SvmR

library(plotly)

p1 <- ggplotly(Graficos$DeclaradaB_svmR.grafico_mp) %>%
        layout(dragmode = "zoom",
                   xaxis = list(
                     title = list(
                       text = "Importancia",
                       standoff = 5)
                     )
               )

p2 <- ggplotly(Graficos$DeclaradaB_svmR.grafico_shad) %>%
        layout(dragmode = "zoom",
               xaxis = list(
                 title = list(
                   text = "Contribución",
                   standoff = 5)))

subplot(
  p1,
  p2,
  nrows = 2,
  titleX = TRUE,
  titleY = TRUE,
  margin = 0.10,
  heights = c(0.40, 0.60)
)

Carga Académica Efectiva

Lm

library(plotly)

p1 <- ggplotly(Graficos$Efectiva_lm.grafico_mp) %>%
        layout(dragmode = "zoom",
                   xaxis = list(
                     title = list(
                       text = "Importancia",
                       standoff = 5)
                     )
               )

p2 <- ggplotly(Graficos$Efectiva_lm.grafico_shad) %>%
        layout(dragmode = "zoom",
               xaxis = list(
                 title = list(
                   text = "Contribución",
                   standoff = 5)))

subplot(
  p1,
  p2,
  nrows = 2,
  titleX = TRUE,
  titleY = TRUE,
  margin = 0.10,
  heights = c(0.40, 0.60)
)

Pls

library(plotly)

p1 <- ggplotly(Graficos$Efectiva_pls.grafico_mp) %>%
        layout(dragmode = "zoom",
                   xaxis = list(
                     title = list(
                       text = "Importancia",
                       standoff = 5)
                     )
               )

p2 <- ggplotly(Graficos$Efectiva_pls.grafico_shad) %>%
        layout(dragmode = "zoom",
               xaxis = list(
                 title = list(
                   text = "Contribución",
                   standoff = 5)))

subplot(
  p1,
  p2,
  nrows = 2,
  titleX = TRUE,
  titleY = TRUE,
  margin = 0.10,
  heights = c(0.40, 0.60)
)

Pcr

library(plotly)

p1 <- ggplotly(Graficos$Efectiva_pcr.grafico_mp) %>%
        layout(dragmode = "zoom",
                   xaxis = list(
                     title = list(
                       text = "Importancia",
                       standoff = 5)))

p2 <- ggplotly(Graficos$Efectiva_pcr.grafico_shad) %>%
        layout(dragmode = "zoom",
               xaxis = list(
                 title = list(
                   text = "Contribución",
                   standoff = 5)))

subplot(
  p1,
  p2,
  nrows = 2,
  titleX = TRUE,
  titleY = TRUE,
  margin = 0.10,
  heights = c(0.40, 0.60)
)

Percibida

Lm

library(plotly)

p1 <- ggplotly(Graficos$Percibida_lm.grafico_mp) %>%
        layout(dragmode = "zoom",
                   xaxis = list(
                     title = list(
                       text = "Importancia",
                       standoff = 5)
                     )
               )

p2 <- ggplotly(Graficos$Percibida_lm.grafico_shad) %>%
        layout(dragmode = "zoom",
               xaxis = list(
                 title = list(
                   text = "Contribución",
                   standoff = 5)))

subplot(
  p1,
  p2,
  nrows = 2,
  titleX = TRUE,
  titleY = TRUE,
  margin = 0.10,
  heights = c(0.40, 0.60)
)