数据可视化是数据分析师和数据科学家表示复杂数据信息并生成有意义见解的最佳方式之一(如果不是最佳方式)。为了充分利用您与利益相关者沟通的机会,我整理了有关Matplotlib颜色映射的有用信息。
正如您在这篇文章中将会看到的,Matplotlib是Python中一个非常灵活且可扩展的可视化库。它提供了从简单图表到完全交互式视觉元素的所有选项。如果您通常不熟悉Python,我建议您在我们开始之前报名参加我们的Python入门课程,以了解其基础知识。就我个人而言,我也经常把Python速查表放在手边,因为它对于常见函数是一个有用的参考。
选择正确的Matplotlib颜色映射
首先需要考虑的是决定使用顺序、发散还是分类色彩映射。选择色彩映射时,还应考虑其他重要因素,包括感知均匀性,即数据值的相等差异被视为颜色的相等差异,以及使用色盲友好的色彩映射选项,以使您的视觉内容对所有观众都能访问。
在选择色彩映射时,还应考虑不同的领域标准。例如,在海洋学研究中的不同深浅的蓝色代表不同的水深。如果您对自己的可视化所需的确切色彩映射不确定,有多种工具和资源可供指导。特别是我们自己的《使用Matplotlib进行数据可视化的介绍》课程可以帮助您解决许多场景问题。
Matplotlib中的不同色彩映射
在Python中,matplotlib.colormaps
模块提供了对内置色彩映射的访问,帮助您为项目选择最合适的方案。以下是最常见的选项类别:
顺序色彩映射
顺序型色图表示从低到高排列的数据。它们从浅色到深色渐变,展示不同级别数据的大小。顺序型色图的例子如热力图中的温度数据,浅色代表较低温度,深色代表较高温度。
假设你有一个包含日期和温度列的数据集。以下代码将创建温度的热力图。
导入所需的库 import numpy as np import pandas as pd import matplotlib.pyplot as plt import matplotlib.colors as mcolors 第一步:从日期列提取月份和日期信息 calendar_data = temperature_data.copy() 创建一个副本以供操作 calendar_data['Month'] = calendar_data['Date'].dt.strftime('%B') calendar_data['Day'] = calendar_data['Date'].dt.day 第二步:定义自然日历序列的月份顺序 month_names = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] 将“月份”列转换为具有指定顺序的分类类型 calendar_data['Month'] = pd.Categorical(calendar_data['Month'], categories=month_names, ordered=True) 第三步:转换数据以创建用于热图的结构化表格 monthly_temperature_table = calendar_data.pivot(index='Month', columns='Day', values='Temperature') 第四步:设置热图的绘图 plt.figure(figsize=(12, 8)) 定义温度范围的自定义归一化(可选) norm = mcolors.Normalize(vmin=15, vmax=35) 使用顺序色彩图创建热图 heatmap = plt.imshow(monthly_temperature_table, cmap='YlOrRd', aspect='auto', norm=norm) 添加颜色条以表示温度 colorbar = plt.colorbar(heatmap, orientation='horizontal') colorbar.set_label('Temperature (°C)', labelpad=10) 标注坐标轴 plt.xlabel('Day of the Month') plt.ylabel('Month') 将y轴刻度设置为显示月份名称而不是数字 plt.yticks(ticks=np.arange(len(month_names)), labels=month_names) 为热图添加标题 plt.title('Monthly Temperature Heatmap (Sequential Colormap)') 显示图表 plt.grid(False) plt.show()
Matplotlib顺序色彩图可视化示例。作者图像
发散色彩图
发散色彩图通过突出显示与中心值双向偏离的数据来强调数据。发散色彩图的正负方向具有对比色。发散色彩图的一个常见应用是在金融数据中,用来表示盈利和亏损。
# 将 'Month' 设为索引 profit_loss_df.set_index('Month', inplace=True) # 设置图形大小 plt.figure(figsize=(8, 4)) # 创建发散色彩图 cmap = plt.cm.RdYlGn # 使用 imshow 显示数据作为热图 im = plt.imshow(profit_loss_df.T, cmap=cmap, aspect='auto', vmin=-np.max(np.abs(profit_loss_data)), vmax=np.max(np.abs(profit_loss_data))) # 添加带有标签的颜色条 cbar = plt.colorbar(im) cbar.set_label('Profit/Loss ($)') # 为每个单元格添加注释 for i, month in enumerate(profit_loss_df.index): plt.text(i, 0, f'{profit_loss_df.loc[month, "Profit/Loss"]:.2f}', ha='center', va='center', color='black') # 设置 x 轴和 y 轴标签和刻度 plt.xlabel('Month') plt.ylabel('') # y 轴无需标签,因为我们只有一个数据行 plt.xticks(ticks=range(len(profit_loss_df.index)), labels=profit_loss_df.index, rotation=45) plt.yticks([]) # 隐藏 y 轴刻度,因为我们只有一个行 # 添加标题 plt.title('Profit/Loss Heatmap (Diverging Colormap)') # 调整布局以获得更好的显示效果 plt.tight_layout() # 显示图表 plt.show()
Matplotlib 发散色彩图可视化示例。作者图像。
循环颜色映射
循环颜色映射对于可视化表示重复或循环模式的数据非常有用,例如角度、波相位或一天中的时间。循环颜色映射的一个应用实例是可视化周期函数的相位,如正弦波。
创建正弦波数据 x = np.linspace(0, 2 * np.pi, 100) 从0到2π的X值(一个完整的周期) y = np.sin(x) Y值(X的正弦) 创建图形和坐标轴 plt.figure(figsize=(10, 6)) 使用循环颜色映射创建散点图 通过正弦波周期中的位置为点着色 points = plt.scatter(x, y, c=x, cmap='twilight', edgecolor='black') 添加颜色条以显示波的相位 cbar = plt.colorbar(points) cbar.set_label('Wave Phase (Radians)', rotation=270, labelpad=15) 标记坐标轴 plt.xlabel('Angle (Radians)') plt.ylabel('Sine Value') 添加标题 plt.title('Sine Wave with Cyclic Colormap (Twilight)') 显示图表 plt.grid(True) plt.show()
Matplotlib循环颜色映射可视化示例。作者图像。
定性颜色映射
定性色彩映射非常适合表示没有特定顺序的分类数据。定性色彩映射的一个常见用例是饼图,其中每个部分代表一个不同的类别,可以轻松区分。
示例分类数据 categories = ['Category A', 'Category B', 'Category C', 'Category D', 'Category E'] values = [20, 35, 25, 10, 10] 设置图形大小 plt.figure(figsize=(8, 8)) 手动定义一个定性色彩映射 colors = ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3'] 手动选择的颜色十六进制代码 创建一个饼图 plt.pie(values, labels=categories, autopct='%1.1f%%', startangle=90, colors=colors) 等宽高比确保饼图被绘制为圆形 plt.axis('equal') 添加标题 plt.title('Pie Chart with Qualitative Colormap') 显示图表 plt.show()
Matplotlib 定性色彩映射可视化示例。作者图片。
彩虹色彩映射
彩虹色彩映射如hsv
在需要广泛色调范围时使用。
生成循环数据 x = np.linspace(0, 2 * np.pi, 500) y = np.sin(x) 使用彩虹色映射创建图表 plt.scatter(x, y, c=x, cmap='hsv', s=50) 添加颜色条 plt.colorbar(label='Phase') 添加标签和标题 plt.xlabel('Angle (radians)') plt.ylabel('Sine Value') plt.title('Cyclic Data Visualization using HSV Colormap') 显示图表 plt.show()
Matplotlib 彩虹色映射可视化示例。作者图片。
感知均匀的色映射
像 inferno
和 plasma
这样的色映射在不同的显示媒介上提供了更好的可见性。
生成合成高程数据 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)) * 100 高程数据 使用 'plasma' 色映射绘制高程数据 plt.contourf(X, Y, Z, cmap='plasma') 添加颜色条 plt.colorbar(label='Elevation (m)') 添加标题和标签 plt.title('Topographic Map (Plasma Colormap)') plt.xlabel('X Coordinate') plt.ylabel('Y Coordinate') 显示图表 plt.show()
Matplotlib感知均匀的色图可视化示例。作者图片。
创建和修改Matplotlib色图
尽管Matplotlib提供了多种内置色图,但在某些情况下,您可能希望自定义颜色。在Matplotlib中创建自定义色图的关键工具是ListedColormap
和LinearSegmentedColormap
。
使用ListedColormap创建自定义色图
ListedColormap
允许您从特定的颜色列表创建色图。当需要对分类数据中的不同类别分配特定颜色时,此方法非常有用。
from matplotlib.colors import ListedColormap 分类数据 categories = ['Category A', 'Category B', 'Category C', 'Category D'] values = [25, 40, 35, 30] 自定义颜色列表用于色图(例如,蓝色、绿色、红色和紫色的阴影) custom_colors = ['#1f77b4', '#2ca02c', '#d62728', '#9467bd'] 使用自定义颜色创建ListedColormap custom_cmap = ListedColormap(custom_colors) 设置图形大小 plt.figure(figsize=(8, 6)) 使用自定义色图创建条形图 bars = plt.bar(categories, values, color=custom_cmap.colors) 添加标题 plt.title('Bar Chart with Custom ListedColormap') 标记轴 plt.xlabel('Categories') plt.ylabel('Values') 显示图表 plt.show()
使用ListedColormap的Matplotlib自定义色图。作者图片。
使用LinearSegmentedColormap创建自定义色图
LinearSegmentedColormap
允许您创建在颜色之间平滑过渡的色图。这值得了解,因为连续数据通常需要渐变颜色变化。在这里,我还指定了我希望用于可视化的区间数。
from matplotlib.colors import LinearSegmentedColormap 创建二维高斯函数的值网格 x = np.linspace(-2, 2, 500) y = np.linspace(-2, 2, 500) X, Y = np.meshgrid(x, y) Z = np.exp(- (X**2 + Y**2)) 定义从蓝色过渡到白色再到红色的自定义颜色映射 colors = ['blue', 'white', 'red'] custom_cmap = LinearSegmentedColormap.from_list('blue_white_red', colors) 调整颜色类的数量(离散级别) 指定级别数(例如,10代表10个不同的颜色带) num_classes = 10 levels = np.linspace(Z.min(), Z.max(), num_classes) 设置图形大小 plt.figure(figsize=(8, 6)) 使用调整后的颜色映射绘制二维高斯函数 contour = plt.contourf(X, Y, Z, levels=levels, cmap=custom_cmap) 添加颜色条以显示离散的颜色类 plt.colorbar(contour, label='Gaussian Function Value') 为坐标轴添加标签 plt.xlabel('X') plt.ylabel('Y') 添加标题 plt.title(f'2D Gaussian with {num_classes} Discrete Color Classes') 显示图表 plt.show()
Matplotlib自定义调整颜色类的数量。作者图像。
自定义颜色范围和强度
您可以通过操作颜色映射的标准化或切片来控制现有颜色映射的强度或颜色范围。在以下示例中,颜色范围被切片以显示介于16至40摄氏度之间的温度。
# 为热图设置绘图 plt.figure(figsize=(12, 8)) # 为温度范围定义自定义归一化 norm = mcolors.Normalize(vmin=16, vmax=40) # 使用连续颜色映射创建热图 heatmap = plt.imshow(monthly_temperature_table, cmap='YlOrRd', aspect='auto', norm=norm) # 添加颜色条以表示温度 colorbar = plt.colorbar(heatmap, orientation='horizontal') colorbar.set_label('Temperature (°C)', labelpad=10) # 标签轴 plt.xlabel('Day of the Month') plt.ylabel('Month') # 设置y轴刻度以显示月份名称而不是数字 plt.yticks(ticks=np.arange(len(month_names)), labels=month_names) # 为热图添加标题 plt.title('Monthly Temperature Heatmap (Sequential Colormap)') # 显示图表 plt.grid(False) plt.show()
Matplotlib自定义颜色范围和强度。作者图像。
组合现有的颜色映射
您还可以通过混合多个颜色映射来组合现有的颜色映射,以创建更复杂的可视化。
from matplotlib.colors import LinearSegmentedColormap, Normalize # 创建合成高程数据 x = np.linspace(-180, 180, 500) # 经度 y = np.linspace(-90, 90, 250) # 纬度 X, Y = np.meshgrid(x, y) Z = 5000 * np.sin(np.sqrt(X**2 + Y**2) * np.pi / 180) # 合成高程数据 # 定义基础颜色映射('viridis' 和 'cividis') cmap1 = plt.get_cmap('viridis') cmap2 = plt.get_cmap('cividis') # 通过混合两种基础颜色映射来创建自定义颜色映射 def blend_colormaps(cmap1, cmap2, blend_ratio=0.5): """Blend two colormaps together.""" c1 = cmap1(np.linspace(0, 1, 256)) c2 = cmap2(np.linspace(0, 1, 256)) blended_colors = (1 - blend_ratio) * c1 + blend_ratio * c2 return LinearSegmentedColormap.from_list('blended_cmap', blended_colors) # 创建混合颜色映射 custom_cmap = blend_colormaps(cmap1, cmap2, blend_ratio=0.5) # 视觉化前归一化数据 norm = Normalize(vmin=-5000, vmax=5000) # 设置图形大小 plt.figure(figsize=(12, 6)) # 使用混合颜色映射绘制合成高程数据 contour = plt.contourf(X, Y, Z, levels=100, cmap=custom_cmap, norm=norm) # 添加颜色条以显示混合颜色映射 plt.colorbar(contour, label='Elevation (meters)') # 为坐标轴添加标签 plt.xlabel('Longitude') plt.ylabel('Latitude') # 添加标题 plt.title('Geographical Elevation Data with Blended Colormap (Viridis + Cividis)') # 显示图表 plt.show()
Matplotlib 结合现有颜色映射。作者图像。
使用 _r 后缀反转颜色映射
你可以在 Matplotlib 中通过在其名称后添加后缀 _r
来反转任何颜色映射。
# 设置热图绘图的参数 plt.figure(figsize=(12, 8)) # 为颜色范围创建自定义归一化 norm = mcolors.Normalize(vmin=16, vmax=40) # 使用 imshow 和顺序颜色映射绘制热图 im = plt.imshow(monthly_temperature_table, cmap='YlOrRd_r', norm=norm, aspect='equal') # 添加带有水平方向的色条 cbar = plt.colorbar(im, orientation='horizontal', pad=0.1) cbar.set_label('Temperature (°C)', labelpad=10) # 为坐标轴添加标签 plt.xlabel('Day of the Month') plt.ylabel('Month') # 设置 y 轴刻度以显示月份名称而不是数字 plt.yticks(ticks=np.arange(len(month_names)), labels=month_names) # 添加标题 plt.title('Temperature Heatmap (Sequential Colormap)') # 显示图表 plt.show()
Matplotlib 使用 _r 后缀反转颜色映射。作者图像。
处理 Matplotlib 颜色映射中的常见错误
当在Matplotlib中处理颜色映射时,可能会遇到影响您工作流程的错误。以下是一些错误以及如何进行故障排除。
AttributeError: module ‘matplotlib’ has no attribute ‘colormaps’
这个错误发生在您使用3.4.0版本之前的Matplotlib访问matplotlib.colormaps
时。颜色映射属性是在Matplotlib 3.4.0中引入的。首先,使用以下代码检查您的Matplotlib版本以排除此错误。
import matplotlib print(matplotlib.__version__)
使用以下pip命令进行升级。
pip install --upgrade matplotlib
如果您在升级Matplotlib版本时遇到问题,尝试以下方法来访问颜色映射。
plt.get_cmap('viridis') # 使用matplotlib.colormaps['viridis']代替
颜色分配不正确
当您传递超出预期范围值或将颜色映射错误应用时,可能会遇到不正确的颜色分配。如果颜色映射本应用于连续数据但却应用于分类数据,或者反之,也可能引起不正确的颜色分配。
为确保您的数据在预期范围内,始终使用vmax
和vmin
参数对数据进行归一化或缩放。
import matplotlib.colors as mcolors 创建一个示例温度数据集 data = np.random.rand(10, 10) * 100 调整范围以匹配您的数据 创建一个颜色归一化实例以将数据缩放到颜色映射的范围 norm = mcolors.Normalize(vmin=0, vmax=100) 使用'viridis'颜色映射和指定的归一化创建热图 plt.imshow(data, cmap='viridis', norm=norm, interpolation='nearest') plt.colorbar() plt.show()
为了更精细的控制,您可以在绘图函数中使用boundaries
或norm
参数显式定义颜色边界。
视觉伪影和意外的结果
当处理离散或低分辨率数据时,可能会遇到意外的色带、过度对比或颜色溢出的问题。当数据范围有限但使用连续色图显示时,就会出现这个问题。
为了解决这个问题,可以使用更多的数据点或调整颜色级别数量来平滑过渡。
增加色图中的箱数 cmap = plt.get_cmap('viridis', 256) plt.imshow(data, cmap=cmap)
在适当的情况下,可以将色图划分为固定级别来处理离散数据。
cmap = plt.get_cmap('inferno', 10) 将色图分为10个离散级别 plt.imshow(data, cmap=cmap)
还可以检查显示设置,并在保存可视化时调整分辨率,以避免出现低分辨率图表
plt.savefig('plot.png', dpi=300) 以更高分辨率保存图形
由于裁剪导致的颜色失真
颜色失真发生在数据包含超出预期颜色范围极端值时。这会导致部分数据被裁剪并分配给颜色映射的最小或最大颜色。
为了避免颜色失真,使用vmin
和vmax
调整颜色限制以匹配数据范围,防止裁剪。
plt.imshow(data, cmap='plasma', vmin=0, vmax=100)
您还应该使用稳健缩放来处理异常值,通过设置排除极端值的自定义限制。
import numpy as np robust_vmin, robust_vmax = np.percentile(data, [2, 98]) 使用百分位数去除极端异常值 plt.imshow(data, cmap='inferno', vmin=robust_vmin, vmax=robust_vmax)
3D图形中颜色映射显示不正确
如果数据在3D表面上的映射有问题,颜色映射可能在3D可视化中显示不正确。要解决这个问题,确保z轴数据标准化以适应颜色映射的预期范围。同时,使用合适的颜色映射限制来捕捉z值的全部范围。
from mpl_toolkits.mplot3d import Axes3D 生成用于3D曲面图样例数据 X, Y = np.meshgrid(np.linspace(-5, 5, 50), np.linspace(-5, 5, 50)) Z = np.sin(np.sqrt(X**2 + Y**2)) 创建一个3D坐标轴对象 ax = plt.axes(projection='3d') 使用'viridis'颜色映射绘制曲面并调整颜色限制 ax.plot_surface(X, Y, Z, cmap='viridis', vmin=np.min(Z), vmax=np.max(Z)) plt.show()
结论
选择正确的颜色映射是一个重要步骤,因为它真正影响了用户如何查看和理解你的数据。在我看来,如果在数据分析上花费了大量时间,而在最后的步骤,也就是你传达发现的部分,做得马虎,这是一个很大的错误。
幸运的是,Matplotlib提供了许多选项,以确保你的视觉讲述了一个引人入胜的故事。加入我们的课程使用Matplotlib进行数据可视化的介绍,成为一名专家。此外,如果你是一个既使用Python也使用Seaborn进行可视化的用户(同时了解两者是很好的),请阅读我们的Seaborn选色快速指南,然后跟随我们的使用Seaborn进行数据可视化的介绍课程。
Source:
https://www.datacamp.com/tutorial/matplotlib-colormaps