Matplotlib:如何避免不同散点图实例间标签颜色重复?
解决Matplotlib 1D散点图中标签颜色重复的问题
问题原因
你遇到的颜色重复问题,是因为Matplotlib在处理c参数的数值时,会针对每个散点图独立归一化颜色范围。比如label1的范围是1-2,label2是3-4,两者的最小值(1和3)都会被映射到colormap的起始颜色,最大值(2和4)映射到结束颜色,导致不同标签值出现相同颜色。
解决方案
方法1:使用全局归一化规则
通过统一所有标签的数值范围,让每个唯一标签对应colormap上的独有色阶:
import matplotlib.pyplot as plt import pandas as pd from matplotlib.colors import Normalize import numpy as np # 生成数据 data1 = list(range(100)) data2 = list(range(100)) data3 = list(range(100)) label1 = [1]*50 + [2]*50 label2 = [3]*50 + [4]*50 label3 = [5]*50 + [6]*50 df = pd.DataFrame({ 'data1': data1, 'data2': data2, 'data3': data3, 'label1': label1, 'label2': label2, 'label3': label3 }) # 收集所有标签,创建全局归一化规则 all_labels = np.concatenate([label1, label2, label3]) unique_labels = np.unique(all_labels) norm = Normalize(vmin=unique_labels.min(), vmax=unique_labels.max()) plt.figure(figsize=(10, 4)) # 所有散点图共用同一个归一化规则 plt.scatter(df['data1'], [0]*len(df), c=df['label1'], norm=norm, alpha=0.6) plt.scatter(df['data2'], [1]*len(df), c=df['label2'], norm=norm, alpha=0.6) plt.scatter(df['data3'], [2]*len(df), c=df['label3'], norm=norm, alpha=0.6) plt.yticks(ticks=[0, 1, 2], labels=['data1', 'data2', 'data3']) plt.xlabel('Value') # 添加颜色条展示标签与颜色的对应关系 sm = plt.cm.ScalarMappable(norm=norm, cmap=plt.cm.viridis) sm.set_array([]) plt.colorbar(sm, ticks=unique_labels, label='Label') plt.tight_layout() plt.show()
原理:Normalize将所有标签的范围统一为1-6,每个标签值会对应colormap上的唯一位置,彻底避免颜色重复。
方法2:手动指定标签-颜色映射
如果需要精确控制每个标签的颜色,可以用字典手动映射:
import matplotlib.pyplot as plt import pandas as pd # 生成数据(同上) data1 = list(range(100)) data2 = list(range(100)) data3 = list(range(100)) label1 = [1]*50 + [2]*50 label2 = [3]*50 + [4]*50 label3 = [5]*50 + [6]*50 df = pd.DataFrame({ 'data1': data1, 'data2': data2, 'data3': data3, 'label1': label1, 'label2': label2, 'label3': label3 }) # 自定义每个标签对应的颜色 color_mapping = { 1: '#ff4500', 2: '#32cd32', 3: '#1e90ff', 4: '#ffd700', 5: '#ff69b4', 6: '#00fa9a' } plt.figure(figsize=(10, 4)) # 将标签转换为对应的颜色列表 plt.scatter(df['data1'], [0]*len(df), color=[color_mapping[l] for l in df['label1']], alpha=0.6) plt.scatter(df['data2'], [1]*len(df), color=[color_mapping[l] for l in df['label2']], alpha=0.6) plt.scatter(df['data3'], [2]*len(df), color=[color_mapping[l] for l in df['label3']], alpha=0.6) plt.yticks(ticks=[0, 1, 2], labels=['data1', 'data2', 'data3']) plt.xlabel('Value') plt.tight_layout() plt.show()
原理:直接用颜色字符串替换标签值,每个标签对应固定颜色,完全避免冲突。
适用场景
- 方法1适合标签数量较多、希望使用渐变色彩的场景,颜色过渡自然。
- 方法2适合标签数量较少、需要精准控制颜色风格的场景。
内容的提问来源于stack exchange,提问作者Bas R
相关产品推荐
相关产品推荐

