You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同一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_silhouette and fviz_cluster use 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_dend defaults 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 same hclust object.

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_colors parameter in fviz_dend forces 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:01:44