同一hclust对象生成的三类聚类图颜色不一致问题求助
Hey there! Great question—this color mismatch is a common gotcha with hierarchical clustering visualizations in factoextra, and it all boils down to how each plot assigns colors under the hood. Let's break it down and fix it.
Why the Colors Don't Match
The core issue is differing color assignment logic across the three factoextra functions:
fviz_silhouetteandfviz_clusteruse your final cluster labels (1, 2, ...,tot_clusters) to map colors directly. Cluster 1 gets the first color in the palette, cluster 2 the second, and so on.fviz_denddefaults to assigning colors based on the order of splits in the dendrogram, not the final cluster labels. The first two branches that split off get the first two colors, even if those branches end up being cluster 3 and 1 in your final grouping. That's why the tree's colors don't align with the other plots, even though they're based on the samehclustobject.
How to Fix the Color Consistency
We'll explicitly define a fixed color-to-cluster mapping and apply it to all three plots. Here's the modified version of your function with this fix:
library(factoextra) library(RColorBrewer) library(scales) # For alpha() to make ellipses transparent Cluster_visualisation <- function(cluster_model, tot_clusters, data, plots) { # Step 1: Extract consistent cluster labels from the hclust object clusters <- cutree(cluster_model, k = tot_clusters) # Step 2: Create a fixed color mapping for each cluster number # Use a qualitative palette, fall back to rainbow if too many clusters if (tot_clusters > max(brewer.pal.info$maxcolors[brewer.pal.info$category == "qual"])) { warning("Too many clusters for standard qualitative palette—using rainbow colors instead") cluster_colors <- rainbow(tot_clusters) } else { cluster_colors <- brewer.pal(tot_clusters, "Set2") } names(cluster_colors) <- 1:tot_clusters # Bind colors to cluster numbers # Step 3: Generate each plot with the fixed color mapping # Dendrogram: Use k_colors to enforce our color scheme plots$dend <- fviz_dend(cluster_model, k = tot_clusters, k_colors = cluster_colors, ggtheme = theme_minimal(), show_labels = FALSE, main = paste("Dendrogram", tot_clusters, "clusters")) # Silhouette plot: Map fill color to cluster labels sil_obj <- silhouette(clusters, dist(data)) plots$sil <- fviz_silhouette(sil_obj, print.summary = FALSE, fill = cluster_colors[as.character(sil_obj$cluster)], color = "white", # White outline for better contrast main = paste("Silhouette plot of", tot_clusters, "clusters"), ggtheme = theme_minimal()) # Cluster plot: Explicitly pass data and cluster labels with our color mapping plots$clust <- fviz_cluster(list(data = data, cluster = clusters), ellipse.type = "convex", ggtheme = theme_minimal(), labelsize = 0, color = cluster_colors[as.character(clusters)], fill = alpha(cluster_colors[as.character(clusters)], 0.2), # Transparent ellipses main = paste("Cluster plot of", tot_clusters ,"clusters")) }
Key Changes Explained
- Explicit cluster labels: We use
cutree()to get the exact cluster assignments, so all plots reference the same grouping. - Fixed color mapping: We bind each cluster number to a specific color, eliminating randomness from dendrogram split order.
- Dendrogram override: The
k_colorsparameter infviz_dendforces the tree to use our color scheme instead of its default split-based logic. - Consistent color passing: Both the silhouette and cluster plots use the same color vector to map cluster labels to colors.
Usage Note
You'll now need to pass your original dataset to the function (since hclust objects don't store raw data), like this:
# Example workflow my_data <- iris[,1:4] dist_matrix <- dist(my_data) hclust_model <- hclust(dist_matrix, method = "ward.D2") plots <- new.env() # Call the function Cluster_visualisation(hclust_model, tot_clusters = 3, data = my_data, plots = plots) # View plots plot(plots$dend) plot(plots$sil) plot(plots$clust)
Now all three plots will use the same color for each cluster number, giving users a consistent experience across visualizations.
内容的提问来源于stack exchange,提问作者Ketosaurus

