Introducción:

El Ranking Web de Universidades, conocido como Webometrics, fue creado en 2004 por el Laboratorio de Cibermetría del CSIC, actualizándose semestralmente. Su objetivo es impulsar la presencia académica en la web y evaluar universidades globalmente. El análisis de conglomerados, destacando el método de k-medias, es crucial para clasificar universidades en grupos homogéneos. Desde una perspectiva externa, se busca explorar el artículo, que aborda la formación de grupos de universidades ecuatorianas basados en variables del ranking mundial. La hipótesis plantea diferencias en Impacto, Apertura y Excelencia entre estos grupos, con el objetivo de formar clusters para las 65 universidades ecuatorianas. Este análisis se realizará desde una perspectiva objetiva y ajena a la autoría del artículo, con el fin de comprender y evaluar sus hallazgos de manera imparcial.

Objetivo:

En este análisis, nos centramos en el artículo que aborda el ranking de universidades ecuatorianas en el contexto del Webometrics. Nuestro objetivo es examinar críticamente la metodología utilizada para agrupar estas universidades según el posicionamiento en el ranking mundial. Nos proponemos comprender los métodos estadísticos aplicados y, al mismo tiempo, identificar posibles áreas de mejora o recomendaciones para futuras investigaciones.

Introducción y Preparación de Datos

options(scipen = 999)    # Eliminar la notación científica
options(digits = 3)      # Número de decimales

# Paquetes
library(pacman)
p_load(
  cluster,
  aplpack,
  fpc,
  foreign,
  TeachingDemos,
  factoextra,
  NbClust,
  ape,
  corrplot,
  DataExplorer,
  funModeling,
  compareGroups,
  tidyverse,
  dendextend,
  igraph,
  FeatureImpCluster,
  flexclust,
  LICORS,
  h2o,
  gghighlight,
  ggthemes)

Preprocesamiento

library(readxl)
datostra <- read_xlsx("trabfin.xlsx")

datostra$Código
##  [1]  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] 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] 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
datostra$Código <- NULL
datostra$Universidad <- NULL
datostra$`Ranking Mundial` <- NULL

La variable “Código” proporciona un identificador único para cada universidad ecuatoriana. En el análisis de conglomerados, “Código” generalmente no aporta información relevante para formar grupos homogéneos La eliminación de “Universidad” simplifica el conjunto de datos en el análisis de conglomerados. Evita que los nombres de las universidades se consideren características importantes para la formación de grupos. La variable “Ranking Mundial” es una combinación lineal de otras tres variables: Impacto, Excelencia y Apertura. En el análisis de conglomerados, mantener “Ranking Mundial” podría introducir dependencia lineal, afectando la interpretación del clustering.

Análisis Descriptivo

Gráfico 1

Porcentaje de datos perdidos por variable

plot_missing(datostra, ggtheme = theme_bw())


En el gráfico 1 se realiza para visualizar la presencia de valores faltantes en el conjunto de datos. Se aprecia que todos los valores resultantes son 0% para cada una de las 3 variables estudiadas.

Gráfico 2

plot_density(datostra,ggtheme = theme_classic())

En el gráfico 2 se ejecutan los códigos para crear un gráfico de densidad, que representa la distribución de los valores para cada variable en el conjunto de datos, se visualiza la forma de las distribuciones y la dispersión de los datos.
Para la variable Impacto se muestra dos picos los cuales indica valores dispersos, para la variable Apertura hay valores extremadamente altos que tiran la distribución hacia la derecha y para la variable Excelencia se distribuye respecto a su media de manera equilibrada pero al final también una cola larga en valores altos.

Gráfico 3

# Histogramas
ggplot(datostra, aes(x = `Impacto (Posición)`)) +
  geom_histogram(binwidth = 100, fill = "skyblue", color = "black") +
  labs(title = "Distribución de Impacto (Posición)")

ggplot(datostra, aes(x = `Apertura (Posición)`)) +
  geom_histogram(binwidth = 100, fill = "lightgreen", color = "black") +
  labs(title = "Distribución de Apertura (Posición)")

ggplot(datostra, aes(x = `Excelencia (Posición)`)) +
  geom_histogram(binwidth = 100, fill = "lightcoral", color = "black") +
  labs(title = "Distribución de Excelencia (Posición)")

Para el gráfico 3 con los histogramas de cada variable se expresa claramente la frecuencia.

Gráfico 4

# Melt para convertir el formato de datos a tidy
datostra_melted <- tidyr::gather(datostra, variable, value)

# Gráfico de cajas y bigotes
ggplot(datostra_melted, aes(x = variable, y = value, fill = variable)) +
  geom_boxplot() +
  labs(title = "Distribución de Variables",
       x = "Variable", y = "Valor", fill = "Variable") +
  theme_minimal() +
  theme(legend.position = "none")  # No mostrar la leyenda

Con el gráfico 4 de cajas se sigue observando variabilidad de los valores de cada variable en estudio, previamente se convirtió el conjunto de datos en formato tidy.
Concluimos así por estandarizar los datos de nuestro conjuntos de datos para una mejor apreciación y con esto un mejor análisis.

# Desición : Estandarizamos
datostra.e <- as.data.frame(scale(datostra))

Resumen

summary(datostra.e)
##  Impacto (Posición) Apertura (Posición) Excelencia (Posición)
##  Min.   :-1.733     Min.   :-2.009      Min.   :-2.618       
##  1st Qu.:-0.948     1st Qu.:-0.734      1st Qu.:-0.558       
##  Median : 0.030     Median : 0.452      Median : 0.204       
##  Mean   : 0.000     Mean   : 0.000      Mean   : 0.000       
##  3rd Qu.: 0.827     3rd Qu.: 0.902      3rd Qu.: 1.078       
##  Max.   : 2.148     Max.   : 0.902      Max.   : 1.078

Análisis multivariado

Aquí se crea la función para el gráfico del método de elbow.

# Cuantos clusters escogemos
# Método de Elbow
wss <- numeric()
for (h in 1:10) {
  b <- kmeans(datostra.e, h)
  wss[h] <- b$tot.withinss
}
wss1 <- data.frame(cluster = c(1:10), wss)
wss1
##    cluster   wss
## 1        1 192.0
## 2        2 102.6
## 3        3  64.6
## 4        4  47.1
## 5        5  38.0
## 6        6  36.6
## 7        7  31.3
## 8        8  23.0
## 9        9  19.0
## 10      10  21.0

Gráfico 5

ggplot(wss1) + aes(cluster, wss) + geom_line(color = "blue") +
  geom_point(color = "blue") +
  geom_vline(xintercept = 3, linetype = 2, col = "red") +
  labs(title = "Método Elbow") +
  scale_x_continuous(breaks = 1:10) +
  theme_classic()

Por el criterio del método de elbow nos indica que el número de cluster apropiado es 3.

NbClust: 30 Indices para determinar el número de clusters.

res.nbclust <- NbClust(
  datostra.e,
  distance = "euclidean",
  min.nc = 2,
  max.nc = 5,
  method = "average",
  index = "all"
)

## *** : The Hubert index is a graphical method of determining the number of clusters.
##                 In the plot of Hubert index, we seek a significant knee that corresponds to a 
##                 significant increase of the value of the measure i.e the significant peak in Hubert
##                 index second differences plot. 
## 

## *** : The D index is a graphical method of determining the number of clusters. 
##                 In the plot of D index, we seek a significant knee (the significant peak in Dindex
##                 second differences plot) that corresponds to a significant increase of the value of
##                 the measure. 
##  
## ******************************************************************* 
## * Among all indices:                                                
## * 7 proposed 2 as the best number of clusters 
## * 10 proposed 3 as the best number of clusters 
## * 6 proposed 5 as the best number of clusters 
## 
##                    ***** Conclusion *****                            
##  
## * According to the majority rule, the best number of clusters is  3 
##  
##  
## *******************************************************************
print(res.nbclust$All.index)
##      KL    CH Hartigan   CCC Scott Marriot TrCovW TraceW Friedman Rubin Cindex
## 2 0.931  6.02    60.71 -8.04  28.6  264019    751  175.3    0.667  1.10  0.377
## 3 3.369 35.68     3.43 -4.30 142.5  103092    767   89.3    6.659  2.15  0.401
## 4 0.450 25.82    38.17 -5.94 158.1  144051    681   84.6    7.683  2.27  0.396
## 5 1.827 40.36    26.82 -2.77 228.6   76048    189   52.0   12.177  3.69  0.385
##      DB Silhouette  Duda Pseudot2   Beale Ratkowsky Ball Ptbiserial  Frey
## 2 0.696      0.327 0.508   58.967  1.6191     0.197 87.6      0.257 0.682
## 3 0.836      0.409 1.010   -0.196 -0.0159     0.410 29.8      0.627 0.516
## 4 0.733      0.379 0.435   50.698  2.1577     0.364 21.1      0.631 0.545
## 5 0.716      0.427 0.398   28.741  2.4464     0.381 10.4      0.658 0.342
##   McClain  Dunn Hubert SDindex Dindex  SDbw
## 2  0.0416 0.246 0.0101    1.23  1.514 1.010
## 3  0.5158 0.239 0.0082    1.14  1.078 0.719
## 4  0.5324 0.239 0.0083    1.25  1.046 0.359
## 5  0.8910 0.192 0.0086    1.29  0.808 0.295

Aquí se concluye lo siguiente, 10 índices propusieron a 3 como el mejor número de cluster.

Desición: Nos quedamos con 3 clusters.

K-means Jerárquico

res.hk <- hkmeans(datostra.e, 3, hc.metric = "euclidean", hc.method = "average", iter.max = 10)
res.hk$tot.withinss
## [1] 64.6
res.hk$cluster
##  [1] 1 1 1 2 1 1 1 1 2 1 1 1 1 1 1 2 2 1 1 2 1 1 1 1 2 1 2 2 2 2 2 2 1 2 2 3 3 3
## [39] 3 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
datos.kJE <- cbind(datostra, grp = res.hk$cluster)
datos.kJE <- mutate(datos.kJE, codigo = 1:n())

Se realiza el metodo de k-means jerárquico usando 3 centroides con una distancia euclidiana y un método de enlace “average” luego se indica el número de iteraciones máxima es 10.

Elegimos el k-means jerárquico porque permite ajustar el número de clusters después de la ejecución inicial, ya que se pueden cortar ramas del dendrograma para obtener un número diferente de clusters otra Ventaja del K-means Jerárquico es que permite construir una jerarquía de clusters, dividiendo los datos en subgrupos de manera iterativa. Esto puede ser útil si se desea una comprensión más detallada de la estructura de los datos a diferentes niveles de granularidad.

Gráfico 6

# Visualización de las soluciones usando ACP
fviz_cluster(res.hk, data = datostra, ellipse.type = "convex") + theme_bw()

El gráfico muestra los grupos identificados en el análisis de clusters en un espacio reducido a través de Análisis de Componentes Principales (ACP).
Las elipses representan los clusters y su forma indica la dispersión de los datos en ese cluster. Esto ayuda a visualizar la separación entre los grupos identificados.

Gráfico 7

# Paleta de colores 
colores <- c("#FF5733", "#33FF57", "#3357FF")

ggplot(data = datos.kJE, aes(x = factor(grp), fill = factor(grp))) +
  geom_bar(color = "white", alpha = 0.8) +
  labs(title = "Frecuencia de Observaciones por Cluster", x = "Cluster", y = "Frecuencia") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_x_discrete(labels = function(x) paste("Cluster ", x)) +
  scale_fill_manual(values = colores) +
  theme(plot.title = element_text(hjust = 0.5),
        axis.text = element_text(size = 10),
        axis.title = element_text(size = 12, face = "bold"),
        legend.position = "none") +
  geom_text(stat = "count", aes(label = ..count..), vjust = -0.5, size = 3) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Este gráfico de barras muestra la frecuencia de observaciones asignadas a cada uno de los tres clusters identificados. Cada barra representa un cluster y su altura muestra la cantidad de observaciones en ese grupo.
Los colores diferentes representan los diferentes clusters.

Gráfico 8

# Grafico de lineas
datos.kJE$grp <- factor(datos.kJE$grp)
datos.kJE %>%
  group_by(grp) %>%
  summarise_all(list(mean)) -> medias
medias$codigo <- NULL

datos.kJE %>%  summarise_if(is.numeric, mean) %>% round(4) -> general
general <- cbind(grp = "general", general)
general$codigo <- NULL

medias  <- as.data.frame(rbind(medias, general))
medias
##       grp Impacto (Posición) Apertura (Posición) Excelencia (Posición)
## 1       1               8124                2751                  4024
## 2       2               5846                5810                  4433
## 3       3              15657                5455                  6355
## 4 general              10994                4616                  5152
gathered_datos.j <- pivot_longer(data = medias, -grp,
                                 names_to = "variable",
                                 values_to = "valor")
gathered_datos.j
## # A tibble: 12 × 3
##    grp     variable               valor
##    <fct>   <chr>                  <dbl>
##  1 1       Impacto (Posición)     8124.
##  2 1       Apertura (Posición)    2751.
##  3 1       Excelencia (Posición)  4024.
##  4 2       Impacto (Posición)     5846.
##  5 2       Apertura (Posición)    5810.
##  6 2       Excelencia (Posición)  4433.
##  7 3       Impacto (Posición)    15657.
##  8 3       Apertura (Posición)    5455.
##  9 3       Excelencia (Posición)  6355.
## 10 general Impacto (Posición)    10994.
## 11 general Apertura (Posición)    4616.
## 12 general Excelencia (Posición)  5152.
ggplot(data = gathered_datos.j) +
  aes(x = variable, y = valor, color = grp, group = grp) +
  geom_point() +
  geom_line() +
  labs(title = "Diagrama de líneas de Medias por Variable y Grupo",
       x = "Variable", y = "Valor", color = "Grupo") +
  theme_bw() +
  theme(legend.position = "top", legend.title = element_blank())


Aquí, cada línea representa la tendencia promedio de las variables para cada uno de los tres clusters identificados.
Se han calculado las medias de cada variable para cada cluster, y este gráfico muestra cómo difieren esas medias entre los grupos.
Ayuda a identificar patrones de comportamiento promedio entre los clusters en relación con las variables.

Convirtiendo la data a formato tidy

Cluster 1:

Interpretación: Este cluster tiene un impacto bajo en comparación con la media general.

Cluster 2:
Interpretación: Este cluster tiene un impacto bajo en comparación con la media general.

Cluster 3:
Interpretación: Este cluster tiene un impacto alto en comparación con la media general.

El ranking utilizado se determina mediante una combinación lineal de las posiciones en “Impacto”, “Excelencia” y “Apertura” con la fórmula:

Ranking=Impacto(0.5)+Excelencia(0.4)+Apertura(0.1)

Los pesos asignados indican la contribución relativa de cada variable al ranking final. Un valor numericamente bajo de ranking señala que una universidad tiene un puesto alto en la tabla de clasificación. La ponderación sugiere que “Impacto” tiene el mayor impacto, seguido por “Excelencia” y “Apertura”.

Ahora, procedamos a revisar las interpretaciones de los clústeres con esta información.

Caracterización de los clusters

library(aplpack)
datos.kJE$grp <- factor(datos.kJE$grp)
datos.kJE %>%
  group_by(grp) %>%
  summarise_all(list(mean)) -> medias2
medias2$codigo <- NULL
medias2$grp<-NULL

datos.kJE %>%  summarise_if(is.numeric, mean) %>% round(4) -> general2

general2$codigo <- NULL

medias2  <- as.data.frame(rbind(medias2, general2))
medias2
##   Impacto (Posición) Apertura (Posición) Excelencia (Posición)
## 1               8124                2751                  4024
## 2               5846                5810                  4433
## 3              15657                5455                  6355
## 4              10994                4616                  5152
aplpack::faces(medias2)

## effect of variables:
##  modified item       Var                    
##  "height of face   " "Impacto (Posición)"   
##  "width of face    " "Apertura (Posición)"  
##  "structure of face" "Excelencia (Posición)"
##  "height of mouth  " "Impacto (Posición)"   
##  "width of mouth   " "Apertura (Posición)"  
##  "smiling          " "Excelencia (Posición)"
##  "height of eyes   " "Impacto (Posición)"   
##  "width of eyes    " "Apertura (Posición)"  
##  "height of hair   " "Excelencia (Posición)"
##  "width of hair   "  "Impacto (Posición)"   
##  "style of hair   "  "Apertura (Posición)"  
##  "height of nose  "  "Excelencia (Posición)"
##  "width of nose   "  "Impacto (Posición)"   
##  "width of ear    "  "Apertura (Posición)"  
##  "height of ear   "  "Excelencia (Posición)"

Grupo Innovador o de Alto Impacto (Cluster 1) : Si este grupo muestra valores bajos en las métricas como apertura y excelencia en relación con los otros grupos, quiere decir que en términos de posición de ranking esta mejor ubicado entre los primeros puestos que los otros dos grupos.

Grupo Prometedor o de Crecimiento (Cluster 2): Si este grupo tiene valores altos en Apertura e intermedios en excelencia, pero bajos en Impacto, quiere decir que su posición es intermedia en el ranking

Grupo en Desarrollo o Tradicional (Cluster 3): Si este grupo se caracteriza por altos valores en métricas como Impacto y Excelencia, quiere decir que a mayor valor numérico en el ranking esta mas abajo que los demás grupos.

Conclusiones y recomendaciones

  • Se realizó el grafico de lineas con los datos sin estandarizar, ya que proporciona una visión directa de cómo se sitúan los clusters en cada variable en relación con el conjunto completo de datos y además a si no pierde la interpretación directa de las variables.

  • Usando la distancia euclidiana y con el método de enlace promedio se obtuvo una similitud con el artículo de 3 clusters, pero con diferentes individuos conformados por 22 , 14 y 29 individuos.

  • Se ha caracterizado a cada grupo (clusters) por sus características correspondientes para una evaluación futura de los grupos de las universidades

Referencias

Vega Falcón, V., Castro Sánchez, F., & Sánchez Martínez, B. (2021). Análisis de clúster de universidades ecuatorianas según su posicionamiento en el ranking mundial. Dilemas contemporáneos: educación, política y valores, 8(3).