为Seaborn热图/聚类图添加第二个颜色条的技术求助
Hey there! I feel your pain—spending hours troubleshooting a small visualization detail is never fun. Let's fix this: the issue here is that seaborn.clustermap doesn't automatically generate a colorbar for the row_colors parameter, since it's primarily meant for grouping/annotating rows. We need to manually create a color mapping and attach it to the figure.
Here's how to do it, depending on whether your vertical bar represents continuous values or categorical labels:
Case 1: Continuous Values in the Vertical Bar
If your row_colors are based on a continuous dataset (like your label array being numerical), use this approach:
import pickle import numpy as np import seaborn as sns import pandas as pd import matplotlib.pyplot as plt from matplotlib.cm import ScalarMappable from matplotlib.colors import Normalize # Load your data feat_mat, freq, label = pickle.load(open('file.pkl', 'rb')) feat_mat_df = pd.DataFrame(feat_mat[4]) # Define your row colors (assuming label is the continuous data for the blue bar) row_colors = label # Draw the clustermap g = sns.clustermap(feat_mat_df, row_colors=row_colors, cmap='Blues') # Use your desired cmap # Create a ScalarMappable to link values to the color map norm = Normalize(vmin=row_colors.min(), vmax=row_colors.max()) sm = ScalarMappable(norm=norm, cmap='Blues') sm.set_array([]) # We just need the color mapping, not actual data # Add the colorbar aligned with the vertical row bar cbar = g.fig.colorbar(sm, ax=g.ax_row_dendrogram, orientation='vertical', pad=0.01) # Customize the colorbar label cbar.set_label('Your Value Description') plt.show()
Case 2: Categorical Labels in the Vertical Bar
If your vertical bar is for categorical groups (e.g., different classes in label), adjust the code to map categories to colors:
import pickle import numpy as np import seaborn as sns import pandas as pd import matplotlib.pyplot as plt from matplotlib.cm import ScalarMappable from matplotlib.colors import Normalize, ListedColormap # Load your data feat_mat, freq, label = pickle.load(open('file.pkl', 'rb')) feat_mat_df = pd.DataFrame(feat_mat[4]) # Map categorical labels to numerical values unique_labels = np.unique(label) label_to_num = {lab: idx for idx, lab in enumerate(unique_labels)} num_labels = [label_to_num[lab] for lab in label] # Create a custom colormap for your categories (using Blues palette here) cmap = ListedColormap(sns.color_palette('Blues', n_colors=len(unique_labels))) # Draw the clustermap g = sns.clustermap(feat_mat_df, row_colors=num_labels, cmap=cmap) # Set up the color mapping norm = Normalize(vmin=0, vmax=len(unique_labels)-1) sm = ScalarMappable(norm=norm, cmap=cmap) sm.set_array([]) # Add the colorbar with category labels cbar = g.fig.colorbar(sm, ax=g.ax_row_dendrogram, orientation='vertical', pad=0.01) cbar.set_ticks(np.arange(len(unique_labels))) cbar.set_ticklabels(unique_labels) cbar.set_label('Category Name') plt.show()
Why Your Previous Attempts Didn't Work
Calling plt.colorbar(row_colors) directly fails because row_colors is just an array of values—it doesn't carry any information about the color map or value range. By creating a ScalarMappable, we explicitly link your values to the color palette, which lets matplotlib generate a proper colorbar that aligns with your clustermap.
内容的提问来源于stack exchange,提问作者Meteorologist

