Matplotlib 色彩映射表(Colormaps)详解:名称、使用和自定义
Matplotlib 是 Python 中最流行的数据可视化库之一,它提供了丰富的色彩映射表(Colormaps)选项,可以帮助我们更好地展示数据。本文将深入探讨 Matplotlib 中的色彩映射表,包括其名称、使用方法和自定义技巧。
1. 什么是色彩映射表?
色彩映射表是一种将数值映射到颜色的方法。在数据可视化中,我们经常需要使用不同的颜色来表示数据的不同值或范围。色彩映射表提供了一种系统化的方法来实现这一目标。
Matplotlib 提供了多种预定义的色彩映射表,每个都有其独特的名称和特点。这些色彩映射表可以分为几个主要类别:
- 顺序色彩映射表(Sequential colormaps)
- 发散色彩映射表(Diverging colormaps)
- 循环色彩映射表(Cyclic colormaps)
- 定性色彩映射表(Qualitative colormaps)
让我们通过一个简单的例子来看看如何使用色彩映射表:
import matplotlib.pyplot as plt
import numpy as np
# 创建数据
x = np.linspace(0, 10, 100)
y = np.sin(x)
# 创建图形
plt.figure(figsize=(10, 6))
plt.scatter(x, y, c=y, cmap='viridis')
plt.colorbar(label='Sin(x)')
plt.title('使用 viridis 色彩映射表 - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
Output:
在这个例子中,我们使用了 ‘viridis’ 色彩映射表来可视化 sin 函数。scatter 函数的 c 参数指定了用于着色的数据,cmap 参数指定了使用的色彩映射表。
2. Matplotlib 中的预定义色彩映射表
Matplotlib 提供了大量预定义的色彩映射表。以下是一些常用的色彩映射表及其特点:
2.1 顺序色彩映射表
顺序色彩映射表适用于表示从低到高或从高到低的连续数据。
- viridis:从深蓝到黄的渐变,是 Matplotlib 的默认色彩映射表
- plasma:从深紫到黄的渐变
- inferno:从黑到黄的渐变
- magma:从黑到白的渐变,经过紫红色
让我们看一个使用 ‘plasma’ 色彩映射表的例子:
import matplotlib.pyplot as plt
import numpy as np
# 创建数据
x = np.linspace(0, 10, 100)
y = np.cos(x)
# 创建图形
plt.figure(figsize=(10, 6))
plt.scatter(x, y, c=y, cmap='plasma')
plt.colorbar(label='Cos(x)')
plt.title('使用 plasma 色彩映射表 - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
Output:
这个例子展示了如何使用 ‘plasma’ 色彩映射表来可视化 cos 函数。
2.2 发散色彩映射表
发散色彩映射表适用于表示具有明确中心点或零点的数据。
- coolwarm:从冷色(蓝)到暖色(红)的渐变
- RdYlBu:从红到黄再到蓝的渐变
- RdBu:从红到白再到蓝的渐变
- PiYG:从紫到黄绿的渐变
下面是一个使用 ‘coolwarm’ 色彩映射表的例子:
import matplotlib.pyplot as plt
import numpy as np
# 创建数据
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))
# 创建图形
plt.figure(figsize=(10, 8))
plt.pcolormesh(X, Y, Z, cmap='coolwarm')
plt.colorbar(label='Sin(sqrt(x^2 + y^2))')
plt.title('使用 coolwarm 色彩映射表 - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
Output:
这个例子展示了如何使用 ‘coolwarm’ 色彩映射表来可视化二维 sin 函数。
2.3 循环色彩映射表
循环色彩映射表适用于表示周期性数据或角度数据。
- hsv:色相-饱和度-明度(Hue-Saturation-Value)循环
- twilight:从紫到橙的平滑循环渐变
- twilight_shifted:twilight 的移位版本
让我们看一个使用 ‘hsv’ 色彩映射表的例子:
import matplotlib.pyplot as plt
import numpy as np
# 创建数据
theta = np.linspace(0, 2*np.pi, 100)
r = np.sin(5*theta)
# 创建图形
plt.figure(figsize=(10, 8))
plt.polar(theta, r, c=theta, cmap='hsv')
plt.colorbar(label='Angle')
plt.title('使用 hsv 色彩映射表 - how2matplotlib.com')
plt.show()
这个例子展示了如何使用 ‘hsv’ 色彩映射表来可视化极坐标下的周期函数。
2.4 定性色彩映射表
定性色彩映射表适用于表示离散的、无序的数据类别。
- Set1, Set2, Set3:不同大小的颜色集合
- Pastel1, Pastel2:柔和的颜色集合
- Paired:成对的颜色集合
下面是一个使用 ‘Set3’ 色彩映射表的例子:
import matplotlib.pyplot as plt
import numpy as np
# 创建数据
categories = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
values = np.random.rand(len(categories))
# 创建图形
plt.figure(figsize=(10, 6))
bars = plt.bar(categories, values, color=plt.cm.Set3(np.linspace(0, 1, len(categories))))
plt.title('使用 Set3 色彩映射表 - how2matplotlib.com')
plt.xlabel('Categories')
plt.ylabel('Values')
# 添加颜色条
sm = plt.cm.ScalarMappable(cmap='Set3', norm=plt.Normalize(vmin=0, vmax=len(categories)-1))
sm.set_array([])
cbar = plt.colorbar(sm)
cbar.set_label('Category Index')
plt.show()
这个例子展示了如何使用 ‘Set3’ 色彩映射表来为不同类别的条形图着色。
3. 如何选择合适的色彩映射表
选择合适的色彩映射表对于有效地传达数据信息至关重要。以下是一些选择色彩映射表的建议:
- 对于连续数据,使用顺序色彩映射表(如 viridis, plasma)
- 对于有中心点的数据,使用发散色彩映射表(如 coolwarm, RdYlBu)
- 对于周期性数据,使用循环色彩映射表(如 hsv, twilight)
- 对于分类数据,使用定性色彩映射表(如 Set1, Paired)
- 考虑色盲友好的色彩映射表(如 viridis, plasma, inferno)
让我们看一个例子,展示如何为不同类型的数据选择合适的色彩映射表:
import matplotlib.pyplot as plt
import numpy as np
# 创建数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.tan(x)
# 创建图形
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15, 5))
# 连续数据使用顺序色彩映射表
im1 = ax1.scatter(x, y1, c=y1, cmap='viridis')
ax1.set_title('连续数据 (viridis) - how2matplotlib.com')
plt.colorbar(im1, ax=ax1)
# 有中心点的数据使用发散色彩映射表
im2 = ax2.scatter(x, y2, c=y2, cmap='coolwarm')
ax2.set_title('有中心点的数据 (coolwarm) - how2matplotlib.com')
plt.colorbar(im2, ax=ax2)
# 周期性数据使用循环色彩映射表
im3 = ax3.scatter(x, y3, c=y3, cmap='hsv')
ax3.set_title('周期性数据 (hsv) - how2matplotlib.com')
plt.colorbar(im3, ax=ax3)
plt.tight_layout()
plt.show()
Output:
这个例子展示了如何为不同类型的数据选择合适的色彩映射表。
4. 自定义色彩映射表
除了使用预定义的色彩映射表,Matplotlib 还允许我们创建自定义的色彩映射表。这在我们需要特定颜色组合或想要强调某些数据范围时非常有用。
4.1 从颜色列表创建色彩映射表
我们可以使用 LinearSegmentedColormap.from_list()
方法从颜色列表创建自定义的色彩映射表。
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np
# 定义颜色列表
colors = ['darkred', 'red', 'orange', 'yellow', 'white']
# 创建自定义色彩映射表
n_bins = 100 # 颜色数量
cmap = mcolors.LinearSegmentedColormap.from_list('custom_cmap', colors, N=n_bins)
# 创建数据
x = np.linspace(0, 10, 100)
y = np.sin(x)
# 创建图形
plt.figure(figsize=(10, 6))
plt.scatter(x, y, c=y, cmap=cmap)
plt.colorbar(label='Sin(x)')
plt.title('使用自定义色彩映射表 - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
Output:
这个例子展示了如何创建一个从深红到白色的自定义色彩映射表。
4.2 修改现有的色彩映射表
我们还可以通过修改现有的色彩映射表来创建新的色彩映射表。例如,我们可以反转色彩映射表或者只使用其中的一部分。
import matplotlib.pyplot as plt
import numpy as np
# 创建数据
x = np.linspace(0, 10, 100)
y = np.cos(x)
# 创建图形
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15, 5))
# 原始色彩映射表
im1 = ax1.scatter(x, y, c=y, cmap='viridis')
ax1.set_title('原始 viridis - how2matplotlib.com')
plt.colorbar(im1, ax=ax1)
# 反转的色彩映射表
im2 = ax2.scatter(x, y, c=y, cmap='viridis_r')
ax2.set_title('反转的 viridis - how2matplotlib.com')
plt.colorbar(im2, ax=ax2)
# 截取的色彩映射表
viridis_part = plt.cm.get_cmap('viridis', 256)
new_cmap = mcolors.ListedColormap(viridis_part(np.linspace(0.2, 0.8, 256)))
im3 = ax3.scatter(x, y, c=y, cmap=new_cmap)
ax3.set_title('截取的 viridis - how2matplotlib.com')
plt.colorbar(im3, ax=ax3)
plt.tight_layout()
plt.show()
这个例子展示了如何反转色彩映射表和截取色彩映射表的一部分。
5. 色彩映射表的高级应用
5.1 离散化色彩映射表
有时我们需要将连续的色彩映射表离散化,以便更清晰地区分不同的数据范围。
import matplotlib.pyplot as plt
import numpy as np
# 创建数据
x = np.linspace(0, 10, 100)
y = np.sin(x)
# 创建图形
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
# 连续色彩映射表
im1 = ax1.scatter(x, y, c=y, cmap='viridis')
ax1.set_title('连续 viridis - how2matplotlib.com')
plt.colorbar(im1, ax=ax1)
# 离散化色彩映射表
n_bins = 5 # 离散化的级别
cmap = plt.cm.get_cmap('viridis', n_bins)
im2 = ax2.scatter(x, y, c=y, cmap=cmap)
ax2.set_title('离散化 viridis - how2matplotlib.com')
plt.colorbar(im2, ax=ax2, ticks=np.linspace(y.min(), y.max(), n_bins+1))
plt.tight_layout()
plt.show()
Output:
这个例子展示了如何将连续的 ‘viridis’ 色彩映射表离散化为 5 个级别。
5.2 使用 BoundaryNorm 进行自定义分段
有时我们需要对数据进行非均匀的分段。这时可以使用 BoundaryNorm
来实现。
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np
# 创建数据
x = np.linspace(0, 10, 100)
y = np.sin(x)
# 定义边界和颜色
bounds = [-1, -0.5, 0, 0.5, 1]
colors = ['red', 'orange', 'lightblue', 'darkblue']
# 创建 BoundaryNorm
norm = mcolors.BoundaryNorm(bounds, len(colors))
# 创建图形
plt.figure(figsize=(10, 6))
plt.scatter(x, y, c=y, cmap=mcolors.ListedColormap(colors), norm=norm)
plt.colorbar(label='Sin(x)', ticks=bounds)
plt.title('使用 BoundaryNorm 的自定义分段 - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
Output:
这个例子展示了如何使用 BoundaryNorm
来创建非均匀的颜色分段。
6. 色彩映射表在不同类型图表中的应用
色彩映射表不仅可以用于散点图,还可以应用于多种类型的图表。让我们看一些例子:
6.1 热力图(Heatmap)
热力图是色彩映射表的一个典型应用场景。
import matplotlib.pyplot as plt
import numpy as np
# 创建数据
data = np.random.rand(10, 10)
# 创建图形
plt.figure(figsize=(10, 8))
plt.imshow(data, cmap='YlOrRd')
plt.colorbar(label='Value')
plt.title('热力图示例 - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
Output:
这个例子展示了如何使用 ‘YlOrRd’ 色彩映射表创建热力图。
6.2 等高线图(Contour Plot)
等高线图也经常使用色彩映射表来表示不同的高度或值。
import matplotlib.pyplot as plt
import numpy as np
# 创建数据
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(X) * np.cos(Y)
# 创建图形
plt.figure(figsize=(10, 8))
cs = plt.contourf(X, Y, Z, cmap='coolwarm', levels=20)
plt.colorbar(cs, label='Z Value')
plt.title('等高线图示例 - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
Output:
这个例子展示了如何使用 ‘coolwarm’ 色彩映射表创建等高线图。
6.3 3D 表面图
色彩映射表也可以应用于 3D 图形。
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
# 创建数据
x = np.linspace(-5, 5, 50)
y = np.linspace(-5, 5, 50)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))
# 创建图形
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(X, Y, Z, cmap='viridis')
fig.colorbar(surf, label='Z Value')
ax.set_title('3D 表面图示例 - how2matplotlib.com')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()
Output:
这个例子展示了如何在 3D 表面图中使用 ‘viridis’ 色彩映射表。
7. 色彩映射表的性能考虑
虽然色彩映射表可以大大提升数据可视化的效果,但在处理大量数据时也需要考虑性能问题。以下是一些提高性能的建议:
- 使用
plt.pcolormesh()
代替plt.imshow()
来绘制大型 2D 数组。 - 对于非常大的数据集,考虑使用
plt.hexbin()
来创建六边形分箱图。 - 使用
plt.scatter()
时,将颜色数据传递给c
参数,而不是使用单独的颜色列表。
让我们看一个使用 plt.hexbin()
的例子:
import matplotlib.pyplot as plt
import numpy as np
# 创建大量数据点
n = 100000
x = np.random.standard_normal(n)
y = 2.0 + 3.0 * x + 4.0 * np.random.standard_normal(n)
# 创建图形
plt.figure(figsize=(10, 8))
plt.hexbin(x, y, gridsize=20, cmap='viridis')
plt.colorbar(label='Count in bin')
plt.title('六边形分箱图示例 - how2matplotlib.com')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
Output:
这个例子展示了如何使用 plt.hexbin()
和 ‘viridis’ 色彩映射表来高效地可视化大量数据点。
8. 色彩映射表的可访问性考虑
在选择色彩映射表时,我们还需要考虑可访问性,特别是对色盲人士的友好程度。以下是一些建议:
- 使用感知均匀的色彩映射表,如 ‘viridis’、’plasma’ 或 ‘inferno’。
- 避免使用红绿组合的色彩映射表,因为红绿色盲是最常见的色盲类型。
- 考虑使用 ColorBrewer 提供的色盲友好色彩映射表。
让我们比较一下常规色彩映射表和色盲友好色彩映射表:
import matplotlib.pyplot as plt
import numpy as np
# 创建数据
x = np.linspace(0, 10, 100)
y = np.sin(x)
# 创建图形
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
# 常规色彩映射表
im1 = ax1.scatter(x, y, c=y, cmap='jet')
ax1.set_title('常规色彩映射表 (jet) - how2matplotlib.com')
plt.colorbar(im1, ax=ax1)
# 色盲友好色彩映射表
im2 = ax2.scatter(x, y, c=y, cmap='viridis')
ax2.set_title('色盲友好色彩映射表 (viridis) - how2matplotlib.com')
plt.colorbar(im2, ax=ax2)
plt.tight_layout()
plt.show()
Output:
这个例子比较了常规的 ‘jet’ 色彩映射表和色盲友好的 ‘viridis’ 色彩映射表。
9. 总结
Matplotlib 的色彩映射表是一个强大的工具,可以大大提升数据可视化的效果和信息传达能力。通过本文,我们详细介绍了 Matplotlib 中各种类型的色彩映射表,包括它们的名称、特点和适用场景。我们还探讨了如何选择合适的色彩映射表,如何创建自定义色彩映射表,以及色彩映射表在不同类型图表中的应用。
在使用色彩映射表时,我们需要考虑数据的性质、可视化的目的、性能要求以及可访问性等因素。通过合理选择和使用色彩映射表,我们可以创建既美观又有效的数据可视化图表,更好地展示和传达数据中的信息。
最后,建议读者在实际应用中多尝试不同的色彩映射表,并根据具体需求进行调整和优化。同时,也要注意色彩映射表的使用不应过度,避免产生视觉混乱或误导观众。通过不断实践和积累经验,相信大家都能掌握色彩映射表这一强大工具,创作出优秀的数据可视化作品。