You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Matplotlib折线图中添加同色系数据点并区分归属

解决Matplotlib折线图与对应数据点颜色匹配的问题

你遇到的问题其实很常见——当用pandas的plot接口分别画折线和散点时,两者默认的颜色循环是独立的,导致散点颜色和折线对不上,尤其是ID多的时候更混乱。这里有两种靠谱的解决办法,帮你轻松搞定:

方法1:获取折线的颜色并复用给散点

在循环里,每次画完折线后,我们可以提取出这条折线的颜色,然后把它传给散点图的c参数,这样散点就和折线颜色完全一致了。

修改后的代码如下:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# 构造数据(特意加了缺失值测试场景)
df = pd.DataFrame({
    'year': ['1988', '1989', '1990', '1988', '1989', '1990', '1988', '1989', '1990'],
    'id': ['1', '1', '1', '2', '2', '2', '3', '3', '3'],
    'money': ['5', '7', '8', '8', np.nan, '3', '7', '8', '10']
}).astype({'year': int, 'id': str, 'money': float})

fig, ax = plt.subplots()
for i in df.id.unique():
    # 画折线,并获取对应的线条对象
    line_plot = df[df['id']==i].plot.line(x='year', y='money', ax=ax, label=f'id = {i}')
    # 提取当前折线的颜色值
    line_color = line_plot.get_lines()[0].get_color()
    # 画散点,指定颜色与折线一致,加白边让点更清晰
    df[df['id']==i].plot.scatter(x='year', y='money', ax=ax, c=line_color, edgecolor='white')

plt.xticks(np.unique(df.year))
plt.legend()
plt.show()

这里的核心是line_plot.get_lines()[0].get_color()——pandas的plot.line返回Axes对象,我们通过get_lines()拿到里面的线条列表,取第一个就是当前ID的折线,再用get_color()提取颜色值,直接传给散点图的c参数即可。

方法2:用单个plot函数同时画折线和标记点(更简便)

其实没必要分开画折线和散点,matplotlib的plot函数本身就支持同时绘制线条和标记点,颜色会自动保持一致,代码也更简洁:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

df = pd.DataFrame({
    'year': ['1988', '1989', '1990', '1988', '1989', '1990', '1988', '1989', '1990'],
    'id': ['1', '1', '1', '2', '2', '2', '3', '3', '3'],
    'money': ['5', '7', '8', '8', np.nan, '3', '7', '8', '10']
}).astype({'year': int, 'id': str, 'money': float})

fig, ax = plt.subplots()
for i in df.id.unique():
    subset = df[df['id']==i].sort_values('year')  # 确保年份按顺序排列
    # 用plot同时绘制折线和标记点,marker指定点样式,linestyle指定折线样式
    ax.plot(subset['year'], subset['money'], marker='o', linestyle='-', label=f'id = {i}')

plt.xticks(np.unique(df.year))
plt.legend()
plt.show()

这种方法的优势很明显:

  • 颜色自动匹配,完全不用手动提取和设置
  • 代码更短,逻辑更清晰
  • 即使有缺失值,折线会自动断开,但存在的数据点依然会显示标记,完美对应所属ID

额外提示:处理大量ID的情况

如果ID数量特别多,matplotlib的默认颜色循环可能不够用,你可以自定义颜色映射,比如用连续色系来生成足够多的独特颜色:

# 用tab20颜色映射,适合多类别场景,第二个参数指定颜色数量
cmap = plt.cm.get_cmap('tab20', len(df.id.unique()))
for idx, i in enumerate(df.id.unique()):
    subset = df[df['id']==i].sort_values('year')
    ax.plot(subset['year'], subset['money'], marker='o', linestyle='-', color=cmap(idx), label=f'id = {i}')

这样不管有多少个ID,每个ID的折线和标记点都会有独特且对应的颜色,再也不会搞混啦!

内容的提问来源于stack exchange,提问作者Marco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:20:52