数据科学 IPython 笔记本 8.10 自定义颜色条

8.10 自定义颜色条

原文:Customizing Colorbars

译者:飞龙

协议:CC BY-NC-SA 4.0

本节是《Python 数据科学手册》(Python Data Science Handbook)的摘录。

绘图图例标识离散点的离散标签。对于基于点,线条或区域颜色的连续标签,带标签的颜色条可能是一个很好的工具。在 Matplotlib 中,颜色条是一个单独的轴域,可以为绘图中的颜色含义提供见解。原书是黑白打印的,但是在线版本是彩色的,你可以在这里看到全彩的图形。我们首先为绘图配置笔记本,并导入我们将使用的函数:

import matplotlib.pyplot as plt
plt.style.use('classic')

%matplotlib inline
import numpy as np

我们在本节中多次看到,可以使用plt.colorbar函数创建最简单的颜色条:

x = np.linspace(0, 10, 1000)
I = np.sin(x) * np.cos(x[:, np.newaxis])

plt.imshow(I)
plt.colorbar();
png

我们现在将讨论一些想法,自定义这些颜色条,并在各种情况下有效地使用它们。

自定义颜色条

可以使用创建可视化的绘图函数的cmap参数指定颜色条:

plt.imshow(I, cmap='gray');
png

所有可用的颜色表都在plt.cm命名空间中;IPython 的 TAB 补全,将为你提供内置选项的完整列表:

plt.cm.<TAB>

但是能够选择颜色表只是第一步:更重要的是如何在选项中做决策!选择结果比你最初预期的要微妙得多。

选择颜色表

可视化中的颜色选择的完全处理,超出了本书的范围,但是为了阅读这个主题和其他内容,请参阅文章“更好的绘图的十个简单的规则”。Matplotlib 的在线文档还有一个关于颜色表选择的有趣讨论

一般来讲,你应该了解三种不同类型的颜色表:

  • 顺序颜色表:它们由连续的颜色序列组成(例如,binaryviridis)。
  • 发散颜色表:这些通常包含两种不同的颜色,显示相对均值的正偏差和负偏差(例如,RdBuPuOr)。
  • 定性颜色表:这些混合颜色没有特定的顺序(例如,rainbowjet)。

jet颜色表是 2.0 版之前 Matplotlib 中的默认值,是定性颜色表的一个示例。它的默认状态非常不幸,因为对于表示定量数据来讲,定性映射往往是不良选择。问题之一是,定性映射通常在尺度增加时不显示任何均匀的亮度变化。

我们可以通过将jet颜色表转换成黑白来看到这一点:

from matplotlib.colors import LinearSegmentedColormap

def grayscale_cmap(cmap):
    """返回给定颜色表的灰度版本"""
    cmap = plt.cm.get_cmap(cmap)
    colors = cmap(np.arange(cmap.N))
    
    # 将 RGBA 转换为感知灰度亮度
    # cf. http://alienryderflex.com/hsp.html
    RGB_weight = [0.299, 0.587, 0.114]
    luminance = np.sqrt(np.dot(colors[:, :3] ** 2, RGB_weight))
    colors[:, :3] = luminance[:, np.newaxis]
        
    return LinearSegmentedColormap.from_list(cmap.name + "_gray", colors, cmap.N)
    

def view_colormap(cmap):
    """使用颜色表的灰度等价物来绘制它"""
    cmap = plt.cm.get_cmap(cmap)
    colors = cmap(np.arange(cmap.N))
    
    cmap = grayscale_cmap(cmap)
    grayscale = cmap(np.arange(cmap.N))
    
    fig, ax = plt.subplots(2, figsize=(6, 2),
                           subplot_kw=dict(xticks=[], yticks=[]))
    ax[0].imshow([colors], extent=[0, 10, 0, 1])
    ax[1].imshow([grayscale], extent=[0, 10, 0, 1])

view_colormap('jet')
png

注意灰度图像中的明亮条纹。即使是全彩色,这种不均匀的亮度意味着,眼睛会被吸引到颜色范围的某些部分,这可能会强调数据集的不重要部分。最好使用例如viridis(Matplotlib 2.0 的默认值)的颜色表,它专门为在整个范围内具有均匀的亮度变化而构建。因此,它不仅可以很好地适应我们的色彩感知,而且可以很好地转换为灰度打印:

view_colormap('viridis')
png

如果你喜欢彩虹图案,连续数据的另一个良好选择是cubehelix颜色表:

view_colormap('cubehelix')
png

对于其他情况,例如显示某些均值的正偏差和负偏差,诸如RdBu(Red-Blue)的双色颜色表可能是有用的。但是,你会在下图中看到,重要的是要注意,在转换为灰度时,正负信息将会丢失!

view_colormap('RdBu')
png

当我们继续时,我们将看到使用其中一些颜色表的示例。

Matplotlib 中有大量的颜色表;要查看它们的列表,可以使用 IPython 来探索plt.cm子模块。对于在 Python 中使用颜色的更加合乎正道的途径,你可以参考 Seaborn 库中的工具和文档(参见“使用 Seaborn 进行可视化”)。

颜色限制和扩展

Matplotlib 允许定制大范围的颜色条。颜色条本身只是plt.Axes的一个实例,所以我们学到的所有轴域和刻度的格式化技巧都适用。颜色条有一些有趣的灵活性:例如,我们可以缩小颜色限制,并通过设置extend属性,在顶部和底部用三角形箭头指示越界值。这可能会派上用场,例如,如果显示受噪声影响的图像:

# 为 1% 的图像像素生成噪声
speckles = (np.random.random(I.shape) < 0.01)
I[speckles] = np.random.normal(0, 3, np.count_nonzero(speckles))

plt.figure(figsize=(10, 3.5))

plt.subplot(1, 2, 1)
plt.imshow(I, cmap='RdBu')
plt.colorbar()

plt.subplot(1, 2, 2)
plt.imshow(I, cmap='RdBu')
plt.colorbar(extend='both')
plt.clim(-1, 1);
png

请注意,在左侧面板中,默认颜色限制会响应噪声像素,并且噪声范围会完全消除我们感兴趣的模式。在右侧面板中,我们手动设置颜色限制,并添加扩展来标识高于或低于这些限制的值。结果是对我们的数据更加有用的可视化。

离散颜色条

默认情况下,颜色表是连续的,但有时你想表示离散值。最简单的方法是使用plt.cm.get_cmap()函数,并传递合适的颜色表的名称以及所需的桶数:

plt.imshow(I, cmap=plt.cm.get_cmap('Blues', 6))
plt.colorbar()
plt.clim(-1, 1);
png

颜色表的离散版本可以像任何其他颜色表一样使用。

示例:手写数字

对于这可能有用的示例,让我们看一些手写数字数据的有趣可视化。
这些数据包含在 Scikit-Learn 中,包含近 2,000 张8x8的缩略图,显示各种手写数字。

现在,让我们首先下载数字数据并使用plt.imshow()可视化几个示例图像:

# 加载数字 0~5 的图像
# 可视化它们中的几个
from sklearn.datasets import load_digits
digits = load_digits(n_class=6)

fig, ax = plt.subplots(8, 8, figsize=(6, 6))
for i, axi in enumerate(ax.flat):
    axi.imshow(digits.images[i], cmap='binary')
    axi.set(xticks=[], yticks=[])
png

因为每个数字由其 64 个像素的亮度定义,我们可以将每个数字视为位于 64 维空间中的点:每个维度代表一个像素的亮度。但是在这种高维空间中可视化关系可能非常困难。解决这个问题的一种方法是使用降维技术,例如流形学习,来减少数据的维度,同时保持感兴趣的关系。降维是无监督机器学习的一个例子,我们将在“什么是机器学习?”中更详细地讨论它。

推迟对这些细节的讨论,让我们看一下这个数字数据的二维流形学习投影(详见“深入分析:流形学习”):

# 使用 IsoMap 将数字投影到二维
from sklearn.manifold import Isomap
iso = Isomap(n_components=2)
projection = iso.fit_transform(digits.data)

我们将使用我们的离散颜色表来查看结果,设置ticksclim来改善所得颜色条的美感:

# 绘制结果
plt.scatter(projection[:, 0], projection[:, 1], lw=0.1,
            c=digits.target, cmap=plt.cm.get_cmap('cubehelix', 6))
plt.colorbar(ticks=range(6), label='digit value')
plt.clim(-0.5, 5.5)
png

该投影还为我们提供了一些数据集内部关系的有趣见解:例如,5 和 3 的范围在此投影中几乎重叠,表明一些手写的五和三难以区分,因此更容易由自动分类算法混淆。其他值,如 0 和 1,更加分散,因此更不容易混淆。这个观察结果与我们的直觉一致,因为 5 和 3 看起来比 0 和 1 更相似。

我们将在第 5 章中返回流形学习和数字分类。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容