# Import required librariesimport numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
# Step 1: Extract month and day information from the date column
calendar_data = temperature_data.copy()# Create a copy to work with
calendar_data['Month']= calendar_data['Date'].dt.strftime('%B')
calendar_data['Day']= calendar_data['Date'].dt.day
# Step 2: Define the order of months for a natural calendar sequence
month_names =['January','February','March','April','May','June','July','August','September','October','November','December']# Convert the 'Month' column to a categorical type with the specified order
calendar_data['Month']= pd.Categorical(calendar_data['Month'], categories=month_names, ordered=True)# Step 3: Pivot the data to create a structured table for the heatmap
monthly_temperature_table = calendar_data.pivot(index='Month', columns='Day', values='Temperature')# Step 4: Set up the plot for the heatmap
plt.figure(figsize=(12,8))# Define a custom normalization for temperature range (optional)
norm = mcolors.Normalize(vmin=15, vmax=35)# Create the heatmap with a sequential colormap
heatmap = plt.imshow(monthly_temperature_table, cmap='YlOrRd', aspect='auto', norm=norm)# Add color bar to represent temperature
colorbar = plt.colorbar(heatmap, orientation='horizontal')
colorbar.set_label('Temperature (°C)', labelpad=10)# Label the axes
plt.xlabel('Day of the Month')
plt.ylabel('Month')# Set y-ticks to display month names instead of numbers
plt.yticks(ticks=np.arange(len(month_names)), labels=month_names)# Add a title to the heatmap
plt.title('Monthly Temperature Heatmap (Sequential Colormap)')# Display the plot
plt.grid(False)
plt.show()技术支持
# Set 'Month' as the index
profit_loss_df.set_index('Month', inplace=True)# Set the figure size
plt.figure(figsize=(8,4))# Create a diverging colormap
cmap = plt.cm.RdYlGn
# Display the data as a heatmap using 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)))# Add color bar with label
cbar = plt.colorbar(im)
cbar.set_label('Profit/Loss ($)')# Add annotations to each cellfor i, month inenumerate(profit_loss_df.index):
plt.text(i,0,f'{profit_loss_df.loc[month,"Profit/Loss"]:.2f}', ha='center', va='center', color='black')# Set x-axis and y-axis labels and ticks
plt.xlabel('Month')
plt.ylabel('')# No label needed for y-axis
plt.xticks(ticks=range(len(profit_loss_df.index)), labels=profit_loss_df.index, rotation=45)
plt.yticks([])# Hide y-axis ticks as we only have one row# Add title
plt.title('Profit/Loss Heatmap (Diverging Colormap)')# Adjust layout for better display
plt.tight_layout()# Show plot
plt.show()技术支持
# Create data for a sine wave
x = np.linspace(0,2* np.pi,100)# X values from 0 to 2π (one complete cycle)
y = np.sin(x)# Y values (sine of X)# Create a figure and axis
plt.figure(figsize=(10,6))# Create a scatter plot with a cyclic colormap# Color points by their position in the sine wave cycle
points = plt.scatter(x, y, c=x, cmap='twilight', edgecolor='black')# Add a color bar to show the phase of the wave
cbar = plt.colorbar(points)
cbar.set_label('Wave Phase (Radians)', rotation=270, labelpad=15)# Label the axes
plt.xlabel('Angle (Radians)')
plt.ylabel('Sine Value')# Add a title
plt.title('Sine Wave with Cyclic Colormap (Twilight)')# Display the plot
plt.grid(True)
plt.show()技术支持
# Sample categorical data
categories =['Category A','Category B','Category C','Category D','Category E']
values =[20,35,25,10,10]# Set the figure size
plt.figure(figsize=(8,8))# Define a qualitative colormap manually
colors =['#8dd3c7','#ffffb3','#bebada','#fb8072','#80b1d3']# Manually selected color hex codes# Create a pie chart
plt.pie(values, labels=categories, autopct='%1.1f%%', startangle=90, colors=colors)# Equal aspect ratio ensures the pie is drawn as a circle
plt.axis('equal')# Add a title
plt.title('Pie Chart with Qualitative Colormap')# Display the chart
plt.show()技术支持
Matplotlib 定性颜色映射可视化示例。图片由作者提供。
彩虹颜色映射
当需要覆盖较宽的色相范围时,可以使用如 hsv 的彩虹颜色映射。
# Generate cyclic data
x = np.linspace(0,2* np.pi,500)
y = np.sin(x)# Create a plot with rainbow colormap
plt.scatter(x, y, c=x, cmap='hsv', s=50)# Add a color bar
plt.colorbar(label='Phase')# Add labels and title
plt.xlabel('Angle (radians)')
plt.ylabel('Sine Value')
plt.title('Cyclic Data Visualization using HSV Colormap')# Display the plot
plt.show()技术支持
Matplotlib 彩虹颜色映射可视化示例。图片由作者提供。
感知均匀型颜色映射
如 inferno 和 plasma 等颜色映射在不同显示介质上具有更好的可读性与可见性。
# Generate synthetic elevation data
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# Elevation data# Plot the elevation data using the 'plasma' colormap
plt.contourf(X, Y, Z, cmap='plasma')# Add a color bar
plt.colorbar(label='Elevation (m)')# Add title and labels
plt.title('Topographic Map (Plasma Colormap)')
plt.xlabel('X Coordinate')
plt.ylabel('Y Coordinate')# Display the plot
plt.show()技术支持
from matplotlib.colors import ListedColormap
# Categorical data
categories =['Category A','Category B','Category C','Category D']
values =[25,40,35,30]# Custom color list for the colormap (e.g., shades of blue, green, red, and purple)
custom_colors =['#1f77b4','#2ca02c','#d62728','#9467bd']# Create a ListedColormap using the custom colors
custom_cmap = ListedColormap(custom_colors)# Set the figure size
plt.figure(figsize=(8,6))# Create a bar plot with the custom colormap
bars = plt.bar(categories, values, color=custom_cmap.colors)# Add a title
plt.title('Bar Chart with Custom ListedColormap')# Label the axes
plt.xlabel('Categories')
plt.ylabel('Values')# Display the plot
plt.show()技术支持
from matplotlib.colors import LinearSegmentedColormap
# Create a grid of values for a 2D Gaussian function
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))# Define a custom colormap that transitions from blue to white to red
colors =['blue','white','red']
custom_cmap = LinearSegmentedColormap.from_list('blue_white_red', colors)# Adjust the number of color classes (discrete levels)# Specify the number of levels (e.g., 10 for 10 distinct color bands)
num_classes =10
levels = np.linspace(Z.min(), Z.max(), num_classes)# Set the figure size
plt.figure(figsize=(8,6))# Plot the 2D Gaussian function with the adjusted colormap
contour = plt.contourf(X, Y, Z, levels=levels, cmap=custom_cmap)# Add a color bar to show the discrete color classes
plt.colorbar(contour, label='Gaussian Function Value')# Add labels for the axes
plt.xlabel('X')
plt.ylabel('Y')# Add a title
plt.title(f'2D Gaussian with {num_classes} Discrete Color Classes')# Display the plot
plt.show()技术支持
# Set up the plot for the heatmap
plt.figure(figsize=(12,8))# Define a custom normalization for temperature range
norm = mcolors.Normalize(vmin=16, vmax=40)# Create the heatmap with a sequential colormap
heatmap = plt.imshow(monthly_temperature_table, cmap='YlOrRd', aspect='auto', norm=norm)# Add color bar to represent temperature
colorbar = plt.colorbar(heatmap, orientation='horizontal')
colorbar.set_label('Temperature (°C)', labelpad=10)# Label the axes
plt.xlabel('Day of the Month')
plt.ylabel('Month')# Set y-ticks to display month names instead of numbers
plt.yticks(ticks=np.arange(len(month_names)), labels=month_names)# Add a title to the heatmap
plt.title('Monthly Temperature Heatmap (Sequential Colormap)')# Display the plot
plt.grid(False)
plt.show()技术支持
Matplotlib 自定义颜色范围与强度。图片由作者提供。
组合现有颜色映射
您还可以通过混合多个颜色映射来组合现有方案,从而创建更复杂的可视化效果。
from matplotlib.colors import LinearSegmentedColormap, Normalize
# Create synthetic elevation data
x = np.linspace(-180,180,500)# Longitude
y = np.linspace(-90,90,250)# Latitude
X, Y = np.meshgrid(x, y)
Z =5000* np.sin(np.sqrt(X**2+ Y**2)* np.pi /180)# Synthetic elevation data# Define the base colormaps ('viridis' and 'cividis')
cmap1 = plt.get_cmap('viridis')
cmap2 = plt.get_cmap('cividis')# Create a custom colormap by blending the two base colormapsdefblend_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)# Create the blended colormap
custom_cmap = blend_colormaps(cmap1, cmap2, blend_ratio=0.5)# Normalize the data for visualization
norm = Normalize(vmin=-5000, vmax=5000)# Set the figure size
plt.figure(figsize=(12,6))# Plot the synthetic elevation data with the blended colormap
contour = plt.contourf(X, Y, Z, levels=100, cmap=custom_cmap, norm=norm)# Add a color bar to show the blended color mapping
plt.colorbar(contour, label='Elevation (meters)')# Add labels for the axes
plt.xlabel('Longitude')
plt.ylabel('Latitude')# Add a title
plt.title('Geographical Elevation Data with Blended Colormap (Viridis + Cividis)')# Display the plot
plt.show()技术支持
Matplotlib 组合现有颜色映射。图片由作者提供。
使用 _r 后缀反转颜色映射
在 Matplotlib 中,您可以通过在名称后添加 _r 后缀来反转任意颜色映射。
# Set up the plot for the heatmap
plt.figure(figsize=(12,8))# Create a custom normalization for the color range
norm = mcolors.Normalize(vmin=16, vmax=40)# Plot the heatmap using imshow with the sequential colormap
im = plt.imshow(monthly_temperature_table, cmap='YlOrRd_r', norm=norm, aspect='equal')# Add a color bar with a horizontal orientation
cbar = plt.colorbar(im, orientation='horizontal', pad=0.1)
cbar.set_label('Temperature (°C)', labelpad=10)# Add labels for the axes
plt.xlabel('Day of the Month')
plt.ylabel('Month')# Set y-ticks to display month names instead of numbers
plt.yticks(ticks=np.arange(len(month_names)), labels=month_names)# Add a title
plt.title('Temperature Heatmap (Sequential Colormap)')# Display the plot
plt.show()技术支持
import matplotlib.colors as mcolors
# Create a sample temperature dataset
data = np.random.rand(10,10)*100# Adjust the range to match your data# Create a color normalization instance to scale the data to the colormap's range
norm = mcolors.Normalize(vmin=0, vmax=100)# Create a heatmap using the 'viridis' colormap and the specified normalization
plt.imshow(data, cmap='viridis', norm=norm, interpolation='nearest')
plt.colorbar()
plt.show()技术支持
import numpy as np
robust_vmin, robust_vmax = np.percentile(data,[2,98])# Use percentiles to remove extreme outliers
plt.imshow(data, cmap='inferno', vmin=robust_vmin, vmax=robust_vmax)技术支持
3D 图中颜色映射显示不正确
如果 3D 曲面中的数据映射存在问题,颜色映射可能无法在 3D 可视化中正确显示。要解决此问题,请确保 z 轴数据已归一化以适配颜色映射的预期范围。同时,使用合适的颜色映射上下限以覆盖 z 值的完整范围。
from mpl_toolkits.mplot3d import Axes3D
# Generate sample data for a 3D surface plot
X, Y = np.meshgrid(np.linspace(-5,5,50), np.linspace(-5,5,50))
Z = np.sin(np.sqrt(X**2+ Y**2))# Create a 3D axes object
ax = plt.axes(projection='3d')# Plot the surface using the 'viridis' colormap and adjusting the color limits
ax.plot_surface(X, Y, Z, cmap='viridis', vmin=np.min(Z), vmax=np.max(Z))
plt.show()技术支持
数据可视化是数据分析师和数据科学家展示复杂信息并产出有意义洞见的最佳方式之一(如果不是最好的话)。为了帮助您更好地与相关方沟通,我整理了有关 Matplotlib 颜色映射的实用信息。
正如您将在本文中看到的,Matplotlib 是 Python 中一个极其灵活且可扩展的可视化库。从简单图表到完全交互式图形,它提供了各种选项。如果您对 Python 还不太熟悉,建议先参加我们的 Introduction to Python 课程,以了解基础知识。就我个人而言,我也会随手放一份 Python Cheat Sheet,因为它是常用函数的便捷参考。
选择合适的 Matplotlib 颜色映射
首先需要考虑的是在顺序型、发散型或类别型颜色映射之间进行选择。选择颜色映射时的其他重要因素包括感知均匀性(即数据值的等距差异应被感知为颜色的等距变化),以及采用对色觉障碍友好的配色选项,使您的可视化对所有受众都更易访问。
选择颜色映射时,您还应考虑不同领域的规范。例如,在海洋学研究中,不同深浅的蓝色表示不同的水深。如果不确定哪种颜色映射适合您的可视化,有多种工具和资源可供参考。尤其是我们的 Introduction to Data Visualization with Matplotlib 课程,可帮助您应对多种情境。
Matplotlib 中的不同颜色映射
在 Python 中,
matplotlib.colormaps模块提供对内置颜色映射的访问,帮助您为项目选择最合适的方案。以下是最常见的几类选项:顺序型颜色映射
顺序型颜色映射用于表示从低到高有序变化的数据。它们通常从浅到深渐变,以展示不同层级的数据幅度。一个示例是用于温度数据的热图,其中较浅的颜色代表较低温度,较深的颜色代表较高温度。
假设您有一个包含日期和温度列的数据集。以下代码将为温度创建热图。
Matplotlib 顺序型颜色映射可视化示例。图片由作者提供
发散型颜色映射
发散型颜色映射用于突出显示相对于中心值两侧的偏差。它们对正负方向采用对比鲜明的颜色。常见应用场景是金融数据中表示盈亏。
Matplotlib 发散型颜色映射可视化示例。图片由作者提供。
循环型颜色映射
循环型颜色映射适用于表示具有重复或周期性模式的数据,例如角度、波形相位或一天中的时间。一个示例是可视化周期函数(如正弦波)的相位。
Matplotlib 循环型颜色映射可视化示例。图片由作者提供。
定性(类别)颜色映射
定性颜色映射非常适合表示无特定顺序的分类数据。常见用例是饼图,其中每个扇区代表不同类别,且易于区分。
Matplotlib 定性颜色映射可视化示例。图片由作者提供。
彩虹颜色映射
当需要覆盖较宽的色相范围时,可以使用如
hsv的彩虹颜色映射。Matplotlib 彩虹颜色映射可视化示例。图片由作者提供。
感知均匀型颜色映射
如
inferno和plasma等颜色映射在不同显示介质上具有更好的可读性与可见性。Matplotlib 感知均匀型颜色映射可视化示例。图片由作者提供。
创建与修改 Matplotlib 颜色映射
尽管 Matplotlib 内置了多种颜色映射,但在某些情况下您可能需要自定义颜色。用于创建自定义颜色映射的关键工具是
ListedColormap和LinearSegmentedColormap。使用 ListedColormap 创建自定义颜色映射
ListedColomap允许您从特定颜色列表创建颜色映射。当您需要为分类数据中的不同类别分配特定颜色时,此方法非常有用。Matplotlib 使用 ListedColormap 的自定义颜色映射。图片由作者提供。
使用 LinearSegmentedColormap 创建自定义颜色映射
LinearSegmentedColormap可创建在颜色之间平滑过渡的颜色映射。这一点值得了解,因为连续型数据通常需要渐变的颜色变化。这里我也指定了希望在图形中显示的分级数量。Matplotlib 自定义并调整颜色分级数量。图片由作者提供。
自定义颜色范围与强度
您可以通过调整归一化方式或对现有颜色映射进行切片来控制其颜色强度或取值范围,仅使用一部分可用颜色。以下示例将颜色范围切片为显示 16 至 40 摄氏度的温度。
Matplotlib 自定义颜色范围与强度。图片由作者提供。
组合现有颜色映射
您还可以通过混合多个颜色映射来组合现有方案,从而创建更复杂的可视化效果。
Matplotlib 组合现有颜色映射。图片由作者提供。
使用 _r 后缀反转颜色映射
在 Matplotlib 中,您可以通过在名称后添加
_r后缀来反转任意颜色映射。Matplotlib 使用 _r 后缀反转颜色映射。图片由作者提供。
处理 Matplotlib 颜色映射中的常见错误
使用 Matplotlib 的颜色映射时,您可能会遇到影响工作流程的错误。以下是一些常见错误及其排查方法。
AttributeError: module 'matplotlib' has no attribute 'colormaps'
当您在 3.4.0 之前的 Matplotlib 版本中访问
matplotlib.colormaps时会出现此错误。colormaps 属性是在 Matplotlib 3.4.0 中引入的。首先使用下面的代码检查您的 Matplotlib 版本来排查此错误。使用以下 pip 命令进行升级。
如果您在升级 Matplotlib 版本时遇到问题,可尝试以下方式访问颜色映射。
颜色分配不正确
当您传入超出预期范围的取值或错误地应用颜色映射时,可能会出现颜色分配不正确。如果将用于连续数据的颜色映射应用于分类数据,或反之亦然,也可能导致错误的颜色分配。
为确保数据位于预期范围内,请始终使用
vmax和vmin参数进行归一化或缩放。若需更精细的控制,您可以在绘图函数中通过
boundaries或norm参数显式定义颜色边界。视觉伪影与意外结果
处理离散或低分辨率数据时,您可能会遇到非期望的色带、过度对比或颜色渗漏。当数据范围有限却使用了连续型颜色映射时,常会出现此问题。
要解决此问题,可增加数据点数量或调整颜色级数以平滑过渡。
对于离散数据,您也可以将颜色映射拆分为固定级数,以便更恰当地呈现。
您还可以检查显示设置并在保存可视化时调整分辨率,避免低分辨率图表。
裁剪导致的颜色失真
当数据包含超出预期颜色范围的极端值时,会发生颜色失真。这会导致部分数据被裁剪,并被赋予颜色映射中的最小或最大颜色。
为避免颜色失真,请使用
vmin和vmax调整颜色范围,使其与数据范围匹配,从而避免裁剪。您还应使用稳健缩放,通过设置自定义上、下限以排除极端值,从而处理离群点。
3D 图中颜色映射显示不正确
如果 3D 曲面中的数据映射存在问题,颜色映射可能无法在 3D 可视化中正确显示。要解决此问题,请确保 z 轴数据已归一化以适配颜色映射的预期范围。同时,使用合适的颜色映射上下限以覆盖 z 值的完整范围。
总结
选择合适的颜色映射至关重要,因为它会深刻影响用户如何查看和理解您的数据。在我看来,把大量时间花在数据分析上,却在最后一步(也就是传达结论的部分)马虎了事,是一个大错误。
好在,Matplotlib 提供了众多选项,确保您的可视化能够讲述一个有说服力的故事。报名参加我们的课程 Introduction to Data Visualization with Matplotlib,成为这方面的专家。另外,如果您既是 Python 用户又使用 Seaborn 进行可视化(两者都会很有帮助),请阅读我们的 Seaborn 选色速查指南,并继续学习 Introduction to Data Visualization with Seaborn 课程。