【数学建模之Python】8.解决画散点图时由于标签非常多导致的重叠现象(利用adjustText库解决) 您所在的位置:网站首页 python散点图标注各点名称 【数学建模之Python】8.解决画散点图时由于标签非常多导致的重叠现象(利用adjustText库解决)

【数学建模之Python】8.解决画散点图时由于标签非常多导致的重叠现象(利用adjustText库解决)

2024-02-15 02:13| 来源: 网络整理| 查看: 265

你们的每个赞都能让我开心好几天✿✿ヽ(°▽°)ノ✿

目录

一、现象陈述

二、、adjustText的了解

1.官方文档

2.参考资料,写的相当好!以下第一个实例就是根据他写的,但我做了进一步的简化与重点提炼

3.用法

4.举例

5.代码

三、改善自我的程序

1.题目

2.代码

3.效果

一、现象陈述

当我们在做可视化时,例如画x-y散点图时,往往需要给散点图上的点标上标签,但是当散点图过多、过于稠密时,matplotlib.pyplot就无法满足让标签清晰的需求了。因此,以下采用adjustText解决该问题

版本声明

Python  3.7.1

adjustText   0.7.3

二、adjustText的了解 1.官方文档 2.参考资料,写的相当好!以下第一个实例就是根据他写的,但我做了进一步的简化与重点提炼 3.用法

adjustText.adjust_text(texts,x=None,y=None,add_objects=None,ax=None,expand_text=(1.05,1.2),expand_points=(1.05,1.2),expand_objects=(1.05,1.2),expand_align=(1.05,1.2),autoalign='xy',va='center',ha='center',force_text=(0.1,0.25),force_points=(0.2,0.5),force_objects=(0.1,0.25),lim=500,precision=0.01,only_move={'objects': 'xy','points': 'xy','text':'xy'},avoid_text=True,avoid_points=True,avoid_self=True,save_steps=False,save_prefix='',save_format='png',add_step_numbers=True,*args,**kwargs)

adjustText中的核心功能都通过调用函数adjust_text来实现,其核心参数如下:

texts:List型,每个元素都是表示单个文字标签对应的matplotlib.text.Text对象

ax:绘制文字标签的目标axe对象,默认为最近一次的axe对象

lim:int型,控制迭代调整文本标签位置的次数,默认为500次

precision:float型,用于决定迭代停止的精度,默认为0.01,即所有标签相互遮挡部分的长和宽占所有标签自身长宽之和的比例,addjust_text会在精度达到precision和迭代次数超过lim这两个条件中至少有一个满足时停止迭代

only_move:字典型,用于指定文本标签与不同对象发生遮挡时的位移策略,键有'points'、'text'和'objects',对应的值可选'xy'、'x'、'y',分别代表竖直和水平方向均调整、只调整水平方向以及只调整竖直方向

arrowprops:字典型,用于设置偏移后的文字标签与原始位置之间的连线样式,下文会作具体演示

save_steps:bool型,用于决定是否保存记录迭代过程中各轮的帧图像,默认为False

save_prefix:str型,当save_steps设置为True时,用于指定中间帧保存的路径,默认为'',即当前工作路径

这个库要自己下,在Anaconda Prompt里pip install adjustText即可

4.举例

(1)简单说明:里面有100个点,100个标签,如果直接画的话,会是这样:

这样可视化看起来非常糟糕,相邻的点的标签重叠在了一起,根本分不清谁是谁! 

(2)使用adjust_text之后:

是不是美观了许多?没有重叠的现象了,但是好像线条不是很好看

(3)再进一步修改!

又有整洁度又有线条,很好看,能够非常清晰的表现出标签的指明对象了

5.代码 import matplotlib.pyplot as plt from adjustText import adjust_text import numpy as np #解决中文显示问题 plt.rcParams['font.sans-serif'] = ['SimHei'] seed = np.random.RandomState(42) # 固定随机数水平 x, y = seed.uniform(0, 1, [2, 100]) # 产生固定的均匀分布随机数 texts = [f'文字{i}' for i in range(x.__len__())] #一、 fig, ax = plt.subplots(figsize=(8, 8)) ax.scatter(x, y, c='SeaGreen', s=10) # 绘制散点 # 绘制所有点对应的文字标签 for x_, y_, text in zip(x, y, texts): plt.text(x_, y_, text, fontsize=12) fig.savefig('原图.png', dpi=300, bbox_inches='tight', pad_inches=0) # 保存图像 #二、 fig, ax = plt.subplots(figsize=(8, 8)) ax.scatter(x, y, c='SeaGreen', s=10) # 绘制散点 # 使用adjustText修正文字重叠现象 new_texts = [plt.text(x_, y_, text, fontsize=12) for x_, y_, text in zip(x, y, texts)] #print(new_texts)了解new_texts是什么类型的 adjust_text(new_texts,only_move={'text': 'x'},arrowprops=dict(arrowstyle='-', color='grey')) fig.savefig('使用adjust_text调整后的图.png', dpi=300, bbox_inches='tight', pad_inches=0) # 保存图像 #三、 fig, ax = plt.subplots(figsize=(8, 8)) ax.scatter(x, y, c='SeaGreen', s=10) # 绘制散点 # 使用adjustText修正文字重叠现象 new_texts = [plt.text(x_, y_, text, fontsize=12) for x_, y_, text in zip(x, y, texts)] adjust_text(new_texts,arrowprops=dict(arrowstyle='->',color='red',lw=1)) fig.savefig('修改线型与颜色后的图.png', dpi=300, bbox_inches='tight', pad_inches=0) plt.show()

(5)注意事项:

要想移植该程序,要明白new_texts的类型是什么!如下图所示

 其次,这个程序运行的时间会久一些,因为采用的算法是迭代多次

三、改善自我的程序

这个问题是在我做数学建模时遇到的,以下是我解决该案例的方法,如果大家不做这个的话可以不用看了,看上面的例题即可。

1.题目

某高校数学系为开展研究生的推荐免试工作,对报名参加推荐的52名学生已修过的6门课的考试分数统计如下表,这6门课的前三门是采用闭卷考试,后三门为开卷考试。我们需要对学生的考试成绩进行合理的排序,得到推荐免试的人选

(《Python数学实验与建模》司守奎例11.3.2)

学生序号数学分析高等代数概率论微分几何抽象代数数值分析A1627164757068A2526557676058A3516355977877A4687785837457A5647055766962A6848179725950A7656757496151A8627364776050A9759480676345A10929288616554A11416750797581A12586656536168A137065761008269A147481761007968A15718577835654A16738580797373A17787476605441A18686660806973A19827773815361A20787682675637A21607063757654A22848986706269A231009995495850A24627166978260A25878777927863A26858280615039A27597266788263A28727674645864A29586666837279A30737570806972A31687460656168A32839279776555A33586059918268A34637666957774A35657373697159A36837773456447A37618069846760A38637773817558A39636070736850A40497166858081A41536360998981A42758078646665A43768079736573A4410096100654750A45889186756560A46687864877979A47878783706260A48687480606352A49748274566559A50898273796359A51757466527055A52707370887969

具体解题过程就不叙述了,重点谈谈标签修正后的效果

2.代码 import numpy as np import pandas as pd from sklearn import decomposition as dc from scipy.stats import zscore import matplotlib.pyplot as plt from adjustText import adjust_text c=pd.read_excel('52名学生的原始考试成绩.xlsx',usecols=np.arange(1,7)) c=c.values.astype(float)#然后我发现第一行汉字没了 print('52名学生的原始考试成绩:\n',c) d=zscore(c)#d是标准化后的c r=np.corrcoef(d.T) f=pd.ExcelWriter('例11.3.2相关系数矩阵.xlsx') pd.DataFrame(r).to_excel(f) f.save() val,vec=np.linalg.eig(r) index=np.argsort(val)[::-1]#特征值降序下标 val=np.sort(val)[::-1].round(4)#降序的特征值 vec=vec[:,index].round(4)#降序特征值对应的特征向量 cs=np.cumsum(val).round(4)#累加和,可以根据这个算出累计贡献率 print('\n特征值为val=',val,'\n累加和cs=',cs) print('前两个因子贡献率:{}>0.8,故公共因子个数选择2个'.format(cs[1]/cs[5])) fa=dc.FactorAnalysis(n_components=2)#取公共因子个数为2,因为前两个方差贡献率超过0.8 fa.fit(d)#求解最大方差的模型,这步必须要有,不然会报错,传入参数为标准化后的原始数据矩阵 print('\n载荷矩阵为:\n',fa.components_.T.round(4))#要转置,有6个标准化指标变量 print('\n特殊方差为:\n',fa.noise_variance_.round(4)) dd=fa.fit_transform(d).round(4)#计算因子得分 print('\n因子得分:\n',dd) w=val[:2]/sum(val[:2])#计算两个因子的权重 df=(dd@w).round(4)#计算每个评价对象的因子总分 tf=np.sum(c,axis=1)#列向量压缩,计算每个评价对象的成绩总分 #构造pandas数据框,第1列到第5列数据分别为因子1得分、因子2得分、因子总分、成绩总分 pdf=pd.DataFrame(np.c_[dd,df,tf,np.arange(1,53).astype(int)], columns=['闭卷科因子得分','开卷科因子得分','因子总分','成绩总分','学号']) f=pd.ExcelWriter('学生的综合评价.xlsx') pdf.to_excel(f,'sheet1') spdf1=pdf.sort_values(by='因子总分',ascending=False)#因子总分从高到低 spdf1.to_excel(f,'sheet2') spdf2=pdf.sort_values(by='成绩总分',ascending=False)#成绩总分从高到低 spdf2.to_excel(f,'sheet3') print('以因子综合得分排序结果为:\n',spdf1,'\n','\n以成绩总分排序结果为:\n',spdf2) f.save() texts=['学号'+str(i) for i in range(1,53)] #print(texts) plt.rc('font',family='SimHei') plt.rc('axes',unicode_minus=False) fig, ax = plt.subplots() ax.scatter(dd[:,0], dd[:,1], c='blue', s=20)#绘制散点,参数:前两个是x,y,第三个是颜色,第四个是大小 new_texts=[plt.text(dd[i,0],dd[i,1],texts[i]) for i in range(len(texts))] #print(new_texts) adjust_text(new_texts,arrowprops=dict(arrowstyle='->',color='red',lw=0.5)) plt.xlabel('闭卷科因子得分') plt.ylabel('开卷科因子得分') plt.savefig('学生因子图.png',dpi=500) #举个例子说明好处,A7的开卷科因子得分高,说明这个学生开卷很厉害,会抄会找答案,但是可以发现闭卷科因子低 #说明他记的东西少,公式到考场上的时候记不住,考的分低 plt.show() 3.效果

使用adjustText的前的原图:

修正后:

(图像放大前)

(图像放大后)

效果明显好了很多

你们的每个赞都能让我开心好几天✿✿ヽ(°▽°)ノ✿



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有