如何基于含时间序列的Pandas DataFrame绘制带颜色标记的散点图?
解决Matplotlib时间序列散点图按第三列着色的问题
嘿,我来帮你搞定这个问题!你代码报错的核心原因有两个:一是plt.plot的着色逻辑和散点图不匹配,二是直接把原始数值传给cm.viridis不会生成正确的颜色映射(颜色映射函数需要0-1之间的归一化数值)。其实有个超简单的实现方式,用plt.scatter就可以完美解决。
推荐方法:使用plt.scatter(最简洁)
plt.scatter天生支持按数值列给散点着色,还能自动处理数值归一化,甚至可以一键添加颜色条来解释颜色对应的含义。直接看修正后的代码:
import pandas as pd import numpy as np import matplotlib.pyplot as plt # 你的数据准备部分 mydatetimes = pd.to_datetime([ '2015-05-01 18:00:12', '2015-05-01 18:01:12', '2015-05-01 18:02:12', '2015-05-01 18:03:12', '2015-05-01 18:04:12', '2015-05-01 18:05:11', '2015-05-01 18:06:11', '2015-05-01 18:07:11', '2015-05-01 18:08:12', '2015-05-01 18:09:12', '2015-05-01 18:10:12', '2015-05-01 18:11:12' ]) myvalues = np.array([45.0, 34.0, 35.0, 45.0, 23.0, 67.0, 78.0, 23.0, 87.0, 32.0, 58.0, 71.0]) myothervalues = np.array([803, 743, 682, 622, 562, 502, 383, 323, 263, 202, 142, 82]) mydatadf = pd.DataFrame({'mydates': mydatetimes, 'data1': myvalues, 'data2': myothervalues}) # 绘制带颜色映射的散点图 plt.figure(figsize=(10, 6)) # c参数传入要用来着色的列,cmap指定颜色映射 scatter = plt.scatter(mydatadf.mydates, mydatadf.data1, c=mydatadf.data2, cmap='viridis') # 添加颜色条,标注颜色对应的数值含义 plt.colorbar(scatter, label='data2 数值') # 旋转X轴日期,避免重叠 plt.xticks(rotation=45) plt.xlabel('日期时间') plt.ylabel('data1 数值') plt.title('按data2着色的时间序列散点图') # 自动调整布局,防止标签被截断 plt.tight_layout() plt.show()
为什么这个方法有效?
plt.scatter的c参数可以直接接受数值数组,它会自动把data2的数值归一化到0-1的范围,对应viridis颜色映射的渐变。- 搭配
plt.colorbar可以直观展示颜色和data2数值的对应关系,让图表更易读。 - 处理时间轴也很友好,Matplotlib会自动识别Pandas的datetime类型,正确显示日期。
如果你非要用plt.plot的修正方法
如果你坚持想用plt.plot来画点,那需要先手动归一化data2的数值,再生成颜色数组,代码如下:
import pandas as pd import numpy as np import matplotlib.pyplot as plt from matplotlib import cm from matplotlib.colors import Normalize # 数据准备和之前一样 mydatetimes = pd.to_datetime([ '2015-05-01 18:00:12', '2015-05-01 18:01:12', '2015-05-01 18:02:12', '2015-05-01 18:03:12', '2015-05-01 18:04:12', '2015-05-01 18:05:11', '2015-05-01 18:06:11', '2015-05-01 18:07:11', '2015-05-01 18:08:12', '2015-05-01 18:09:12', '2015-05-01 18:10:12', '2015-05-01 18:11:12' ]) myvalues = np.array([45.0, 34.0, 35.0, 45.0, 23.0, 67.0, 78.0, 23.0, 87.0, 32.0, 58.0, 71.0]) myothervalues = np.array([803, 743, 682, 622, 562, 502, 383, 323, 263, 202, 142, 82]) mydatadf = pd.DataFrame({'mydates': mydatetimes, 'data1': myvalues, 'data2': myothervalues}) # 归一化data2到0-1范围 norm = Normalize(vmin=mydatadf.data2.min(), vmax=mydatadf.data2.max()) colors = cm.viridis(norm(mydatadf.data2)) plt.figure(figsize=(10, 6)) # 逐个绘制每个点,指定颜色 for date, val, color in zip(mydatadf.mydates, mydatadf.data1, colors): plt.plot(date, val, '.', color=color) # 手动创建颜色条 sm = cm.ScalarMappable(norm=norm, cmap='viridis') sm.set_array([]) plt.colorbar(sm, label='data2 数值') plt.xticks(rotation=45) plt.xlabel('日期时间') plt.ylabel('data1 数值') plt.title('按data2着色的时间序列散点图(使用plt.plot)') plt.tight_layout() plt.show()
不过说实话,这种方法比plt.scatter麻烦很多,毕竟plt.plot主要是用来画连续线条的,处理散点着色不是它的强项,所以还是推荐第一种方法。
内容的提问来源于stack exchange,提问作者user2699676
相关产品推荐
相关产品推荐

