如何在seaborn objects带标签散点图中添加趋势线与x=y线?
Seaborn Objects 散点图标签与趋势线共存及添加x=y线问题
问题描述
使用seaborn.objects接口绘制带标签的散点图时,若在Plot初始化时指定text='label',合并标签与趋势线代码后仅显示标签,单独绘制带标签的散点图、带趋势线的散点图均正常。需解决两个问题:
- 如何让标签与趋势线同时显示在一张图中?
- 如何在这类图中添加x=y线?
问题1:标签与趋势线共存的解决方案
问题原因
当在Plot全局指定text='label'时,后续所有add()的元素会默认继承该参数,但PolyFit()生成的趋势线数据不包含label字段,导致趋势线无法正常渲染。
修正代码
不在Plot全局设置text参数,而是在添加Text元素时单独指定text='label':
import seaborn.objects as so from matplotlib import pyplot as plt import pandas as pd import numpy as np np.random.seed(42) num_points = 10 df = pd.DataFrame({'x': np.random.randint(1, 100, size=num_points), 'y': np.random.randint(1, 100, size=num_points), 'label' : [chr(i + 65) for i in range(num_points)]}) fig, ax = plt.subplots() p = so.Plot(data=df, x='x', y='y') \ .add(so.Dot(marker='o')) \ .add(so.Text(halign='left'), text='label') \ .add(so.Line(color='orange'), so.PolyFit()) p.on(ax).show()
执行后即可同时显示散点、标签和趋势线。
问题2:添加x=y线的两种方法
方法1:使用Matplotlib原生API绘制
在Seaborn Objects绘图完成后,获取坐标轴范围,直接绘制x=y线:
import seaborn.objects as so from matplotlib import pyplot as plt import pandas as pd import numpy as np np.random.seed(42) num_points = 10 df = pd.DataFrame({'x': np.random.randint(1, 100, size=num_points), 'y': np.random.randint(1, 100, size=num_points), 'label' : [chr(i + 65) for i in range(num_points)]}) fig, ax = plt.subplots() p = so.Plot(data=df, x='x', y='y') \ .add(so.Dot(marker='o')) \ .add(so.Text(halign='left'), text='label') \ .add(so.Line(color='orange'), so.PolyFit()) p.on(ax) # 添加x=y虚线 xlim = ax.get_xlim() ylim = ax.get_ylim() min_val = min(xlim[0], ylim[0]) max_val = max(xlim[1], ylim[1]) ax.plot([min_val, max_val], [min_val, max_val], color='red', linestyle='--') plt.show()
方法2:使用Seaborn Objects接口添加
生成包含x=y范围数据的临时DataFrame,通过add(so.Line())添加:
import seaborn.objects as so from matplotlib import pyplot as plt import pandas as pd import numpy as np np.random.seed(42) num_points = 10 df = pd.DataFrame({'x': np.random.randint(1, 100, size=num_points), 'y': np.random.randint(1, 100, size=num_points), 'label' : [chr(i + 65) for i in range(num_points)]}) # 生成x=y的范围数据 x_y_range = pd.DataFrame({ 'x': [df[['x','y']].min().min(), df[['x','y']].max().max()], 'y': [df[['x','y']].min().min(), df[['x','y']].max().max()] }) fig, ax = plt.subplots() p = so.Plot(data=df, x='x', y='y') \ .add(so.Dot(marker='o')) \ .add(so.Text(halign='left'), text='label') \ .add(so.Line(color='orange'), so.PolyFit()) \ .add(so.Line(color='red', linestyle='--'), data=x_y_range) p.on(ax).show()
内容的提问来源于stack exchange,提问作者doine
相关产品推荐
相关产品推荐

