Machine Learning. Taller 3: Análisis de clustering
Etapa 1: Dominio del problema
Una consultora de desarrollo de software busca identificar patrones naturales en sus proyectos para mejorar la gestión y toma de decisiones. Para ello, se aplicarán técnicas de clustering sobre los datos previamente procesados con el objetivo de:
Identificar grupos naturales de proyectos con características similares
Caracterizar cada grupo para entender sus particularidades
Utilizar esta información para mejorar la planificación de futuros proyectos
Preguntas a responder
¿Qué exactamente deseamos hacer?
Descubrir patrones naturales en los proyectos de software
Agrupar proyectos similares
Caracterizar los grupos encontrados
¿Es factible alcanzar lo que buscamos con los datos disponibles?
Sí, las variables disponibles permiten identificar similitudes entre proyectos
¿Cómo podemos lograrlo?
Aplicando técnicas de clustering no supervisado
Analizando las características de los grupos resultantes
¿Qué tipo de problema se va a resolver?
Problema de aprendizaje no supervisado (clustering)
¿El objetivo es?
Descubrir y caracterizar grupos naturales de proyectos
Etapa 2: Preparación de datos
En esta etapa, cargaremos los datos preprocesados de la práctica anterior y los prepararemos específicamente para el análisis de clustering.
# Cargar librerías necesariaslibrary(tidyverse) # Para manipulación de datoslibrary(cluster) # Para análisis de clusteringlibrary(factoextra) # Para visualización de clusterslibrary(NbClust) # Para determinar número óptimo de clusterslibrary(gridExtra) # Para organizar gráficoslibrary(scales) # Para formato de escalaslibrary(knitr) # Para tablas# Cargar datos preprocesadosdatos <-read.csv("datos_proyectos_software_limpio.csv")# Seleccionar variables para clusteringdatos_cluster <- datos %>%select(tamano_equipo, duracion_meses, errores_por_kloc, puntuacion_calidad, satisfaccion_cliente)# Normalizar datosdatos_norm <-scale(datos_cluster)# Mostrar estructura de los datos normalizadosstr(datos_norm)
Utilizaremos varios métodos para determinar el número óptimo de clusters:
Método del codo
Método de la silueta
Método de gap statistic
# Método del Codo: # Mide la variación dentro de los clusters para diferentes k. # En el gráfico, busca un "codo" o punto donde agregar más clusters ya no reduce# significativamente la variación.# Método de la Silueta:# Evalúa qué tan similar es cada punto a su propio cluster vs. otros clusters. # Mayor valor = mejor separación entre clusters. El k con el valor más alto es # óptimo.# Gap Statistic:# Compara clusters con datos aleatorios. Mide la diferencia ("gap") entre ellos.# El k con la mayor diferencia es óptimo, indicando clusters significativamente# mejores que agrupaciones aleatorias.set.seed(1987)# Método del codofviz_nbclust(datos_norm, kmeans, method ="wss") +labs(title ="Método del Codo")# Método de la siluetafviz_nbclust(datos_norm, kmeans, method ="silhouette") +labs(title ="Método de la Silueta")# Método gap statisticgap_stat <-clusGap(datos_norm, FUN = kmeans, nstart =25,K.max =10, B =50)fviz_gap_stat(gap_stat) +labs(title ="Método Gap Statistic")
Método del Codo
Método de la Silueta
Método Gap Statistic - El pico más alto sugiere el número óptimo de clusters.
b. Aplicación de K-means
Basados en los resultados anteriores, aplicamos K-means con el número óptimo de clusters.
# Aplicar K-means con el número óptimo de clustersset.seed(1987)k_optimo <-3# Basado en los resultados anterioreskmeans_result <-kmeans(datos_norm, centers = k_optimo, nstart =25)# Visualizar clustersfviz_cluster(kmeans_result, data = datos_norm,ellipse.type ="convex",palette ="jco",ggtheme =theme_minimal())
# Agregar etiquetas de cluster a los datos originalesdatos$cluster <-as.factor(kmeans_result$cluster)
c. Caracterización de clusters
Analizamos las características de cada cluster:
# Estadísticas descriptivas por clusterstats_clusters <- datos %>%group_by(cluster) %>%summarise(n =n(),tamano_equipo_med =mean(tamano_equipo),duracion_meses_med =mean(duracion_meses),errores_kloc_med =mean(errores_por_kloc),puntuacion_calidad_med =mean(puntuacion_calidad),satisfaccion_med =mean(satisfaccion_cliente) )# Mostrar tabla de estadísticaskable(stats_clusters, digits =2,col.names =c("Cluster", "N", "Tamaño Equipo", "Duración", "Errores/KLOC", "Calidad", "Satisfacción"))
Estadísticas descriptivas por cluster
Cluster
N
Tamaño Equipo
Duración
Errores/KLOC
Calidad
Satisfacción
1
303
9.25
4.71
0.86
66.20
74.44
2
158
9.41
16.20
1.65
74.96
83.87
3
435
8.60
4.79
0.97
81.06
88.80
# Visualización de características por clusterdatos_long <- datos %>%select(cluster, tamano_equipo, duracion_meses, errores_por_kloc, puntuacion_calidad, satisfaccion_cliente) %>%pivot_longer(!cluster, names_to ="variable", values_to ="valor")ggplot(datos_long, aes(x = cluster, y = valor, fill = cluster)) +geom_boxplot() +facet_wrap(~variable, scales ="free_y") +theme_minimal() +labs(title ="Características por Cluster",x ="Cluster", y ="Valor") +theme(legend.position ="none")
d. Interpretación de resultados
Descripción de clusters
Basados en el análisis anterior, podemos caracterizar cada cluster:
# Estadísticas de siluetasi_summary <-summary(silhouette_score)cat("Coeficiente de silueta promedio:", round(si_summary$avg.width, 3))
Coeficiente de silueta promedio: 0.245
Recomendaciones
Basados en los resultados del análisis de clustering, se pueden hacer las siguientes recomendaciones:
Para proyectos de alto rendimiento:
Mantener el tamaño de equipo óptimo identificado
Continuar con las prácticas de calidad existentes
Documentar y replicar las mejores prácticas
Para proyectos estándar:
Implementar mejoras graduales en procesos de calidad
Evaluar la posibilidad de optimizar el tamaño del equipo
Establecer metas de mejora continua
Para proyectos desafiantes:
Revisar y ajustar las prácticas de gestión de proyectos
Implementar controles de calidad más estrictos
Considerar la restructuración de equipos grandes
Etapa 3: Análisis de clustering - jerárquico
# Matriz de distancia y clusteringdist_matrix <-dist(datos_norm, method ="euclidean")hc_result <-hclust(dist_matrix, method ="average")# Dendrogramafviz_dend(hc_result, k =3,cex =0.6,palette ="jco",rect =TRUE) +theme_minimal() +labs(title ="Dendrograma de Clustering Jerárquico")
Warning: The `<scale>` argument of `guides()` cannot be `FALSE`. Use "none" instead as
of ggplot2 3.3.4.
ℹ The deprecated feature was likely used in the factoextra package.
Please report the issue at <https://github.com/kassambara/factoextra/issues>.
Ahora mostramos los grupos tal como se hizo con k-means
# Estadísticas de siluetasi_summary <-summary(silhouette_hc)cat("Coeficiente de silueta promedio:", round(si_summary$avg.width, 3))
Coeficiente de silueta promedio: 0.226
Comparamos los resultados con kmeans
datos_long_combined <- datos %>%select(cluster, cluster_jerarquico, tamano_equipo, duracion_meses, errores_por_kloc, puntuacion_calidad, satisfaccion_cliente) %>%pivot_longer(cols =c(tamano_equipo:satisfaccion_cliente), names_to ="variable", values_to ="valor") %>%pivot_longer(cols =c(cluster, cluster_jerarquico), names_to ="metodo", values_to ="cluster_num")ggplot(datos_long_combined, aes(x = cluster_num, y = valor, fill = metodo)) +geom_boxplot() +facet_wrap(~variable, scales ="free_y") +theme_minimal() +labs(title ="Comparación de Características por Método y Cluster",x ="Cluster", y ="Valor") +theme(legend.position ="bottom")
Caracterización
Cluster 1
Proyectos eficientes con equipos pequeños y alta calidad
Cluster 2
Proyectos intermedios con métricas promedio
Cluster 3
Proyectos complejos con equipos grandes y desafíos de calidad
Preparación para siguientes prácticas
# Guardar resultados de clustering para la siguiente prácticadatos$cluster_label <-paste("Cluster", datos$cluster)write.csv(datos, "datos_proyectos_software_clusters.csv", row.names =FALSE)
Los resultados de este análisis servirán como base para:
Práctica 4: Desarrollo de una aplicación Shiny para visualización y análisis interactivo