如何基于matplotlib pyplot为电池电量时序数据创建自定义颜色条
自定义电池电量时序图颜色条的实现方案
当然可以实现你想要的自定义颜色映射效果!结合Matplotlib的颜色映射和归一化工具,完全能做到100%→绿色、15%→红色、低于15%→黑色的视觉效果。下面是完整的代码示例和关键细节解释:
1. 核心思路
我们需要分两步构建颜色规则:
- 先创建100%到15%之间的绿→红线性渐变
- 再把低于15%的数值区间强制映射为黑色
最后用边界归一化工具确保颜色和电量值准确对应。
2. 完整可运行代码
假设你的电量数据存在battery_levels列表中(1944个元素,范围0~1),时间序列可以直接用索引生成:
import matplotlib.pyplot as plt from matplotlib.colors import LinearSegmentedColormap, BoundaryNorm import numpy as np # 替换成你实际的battery_levels数据 battery_levels = np.linspace(1.0, 0.08, 1944) # 模拟从100%降到8%的递减数据 time_points = np.arange(len(battery_levels)) # 第一步:创建绿→红的基础颜色映射(对应15%~100%) base_colors = [(0, 1, 0), (1, 0, 0)] # 绿色(100%)、红色(15%) base_cmap = LinearSegmentedColormap.from_list("battery_base", base_colors, N=256) # 第二步:扩展映射,把低于15%的部分改成黑色 cmap_data = base_cmap(np.linspace(0, 1, 256)) black_rgba = np.array([0, 0, 0, 1]) # 不透明黑色 # 计算15%对应的颜色索引,把之前的所有位置替换为黑色 threshold_idx = int(0.15 * 256) cmap_data[:threshold_idx] = black_rgba custom_cmap = LinearSegmentedColormap.from_list("custom_battery", cmap_data) # 创建边界归一化,明确区间规则:<15%、15%~100% bounds = [0, 0.15, 1.0] norm = BoundaryNorm(bounds, custom_cmap.N) # 绘制可视化图表 fig, ax = plt.subplots(figsize=(12, 6)) # 用scatter展示每个数据点的颜色(如果要折线渐变可以用LineCollection,scatter更简单直观) scatter_plot = ax.scatter(time_points, battery_levels, c=battery_levels, cmap=custom_cmap, norm=norm, s=6, alpha=0.8) # 添加自定义颜色条 color_bar = plt.colorbar(scatter_plot, ax=ax) color_bar.set_label('电池电量 (%)', fontsize=12) # 手动设置颜色条刻度,清晰展示关键阈值 color_bar.set_ticks([0, 0.15, 1.0]) color_bar.set_ticklabels(['<15%', '15%', '100%']) # 美化图表 ax.set_title('电池电量随时间变化(自定义颜色映射)', fontsize=14, pad=15) ax.set_xlabel('时间点', fontsize=12) ax.set_ylabel('电量百分比', fontsize=12) ax.grid(True, linestyle='--', alpha=0.3) plt.tight_layout() plt.show()
3. 关键细节说明
- 颜色映射扩展:我们先生成基础的绿红渐变,再通过修改颜色数组的方式把低于15%的部分替换成黑色,这种方式比直接定义分段映射更灵活。
- BoundaryNorm的作用:它能帮我们严格区分不同数值区间的颜色规则,确保低于0.15的所有值都显示黑色,不会出现渐变过渡。
- 可视化选择:用
scatter可以给每个数据点单独上色,适合展示高密度的时序数据;如果你想要折线的颜色渐变效果,可以用LineCollection,但实现起来稍复杂,对于1944个点来说,scatter的展示效果已经足够清晰。
4. 适配你现有代码的小技巧
如果你的原代码用的是plt.plot绘制折线,可以替换成以下方式(实现折线颜色随电量变化):
# 替换原plot语句 from matplotlib.collections import LineCollection # 构建线段数据 segments = [] for i in range(len(time_points)-1): x = [time_points[i], time_points[i+1]] y = [battery_levels[i], battery_levels[i+1]] segments.append(np.array([x, y]).T) # 创建线段集合并上色 lc = LineCollection(segments, cmap=custom_cmap, norm=norm, linewidth=2) lc.set_array(battery_levels[:-1]) # 给每个线段分配对应的电量值 ax.add_collection(lc)
内容的提问来源于stack exchange,提问作者Quertsy
相关产品推荐
相关产品推荐

