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

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

目录

一、现象陈述

二、、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)

学生序号数学分析高等代数概率论微分几何抽象代数数值分析
A1627164757068
A2526557676058
A3516355977877
A4687785837457
A5647055766962
A6848179725950
A7656757496151
A8627364776050
A9759480676345
A10929288616554
A11416750797581
A12586656536168
A137065761008269
A147481761007968
A15718577835654
A16738580797373
A17787476605441
A18686660806973
A19827773815361
A20787682675637
A21607063757654
A22848986706269
A231009995495850
A24627166978260
A25878777927863
A26858280615039
A27597266788263
A28727674645864
A29586666837279
A30737570806972
A31687460656168
A32839279776555
A33586059918268
A34637666957774
A35657373697159
A36837773456447
A37618069846760
A38637773817558
A39636070736850
A40497166858081
A41536360998981
A42758078646665
A43768079736573
A4410096100654750
A45889186756560
A46687864877979
A47878783706260
A48687480606352
A49748274566559
A50898273796359
A51757466527055
A52707370887969

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

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的前的原图:

修正后:

(图像放大前)

(图像放大后)

效果明显好了很多

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

  • 17
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Python中使用plt.plot函数可以。具体步骤如下: 1. 导入matplotlib中的pyplot块:import matplotlib.pyplot as plt 2. 准备数据,例如:x = [1, 2, 3, 4, 5],y = [2, 4, 6, 8, 10] 3. 使用plt.plot函数:plt.plot(x, y, 'o') 其中,'o'表示使用圆点作为的标记。 4. 可以设置的标题、x轴和y轴的标签等属性:plt.title('Scatter Plot'),plt.xlabel('X'),plt.ylabel('Y') 5. 最后使用plt.show()函数显示。 完整代码如下: import matplotlib.pyplot as plt x = [1, 2, 3, 4, 5] y = [2, 4, 6, 8, 10] plt.plot(x, y, 'o') plt.title('Scatter Plot') plt.xlabel('X') plt.ylabel('Y') plt.show() ### 回答2: Python语言中,使用matplotlib.pyplot中的plot函数可以绘制。 绘制的步骤如下: 1. 导入必要的 在使用plot函数之前,需要首先导入matplotlib.pyplot,同还可以根据需要导入其他,例如numpy,以便进行数据处理。 import matplotlib.pyplot as plt import numpy as np 2. 准备数据 准备要绘制的数据,可以将数据放在一个二维数组中,每个元素表示一个点的坐标。 x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] y = [2, 4, 5, 7, 6, 8, 9, 10, 12, 11] 3. 绘制 调用plot函数,设置参数,。 plt.scatter(x, y, s=50, c='r', marker='o') plt.title('Scatter Plot') plt.xlabel('X-axis') plt.ylabel('Y-axis') plt.show() 其中,参数x和y分别表示横坐标和纵坐标的数据,s参数表示点的大小,c参数表示点的颜色,marker参数表示点的形状,title、xlabel和ylabel分别是像的标题和坐标轴的标签,show函数表示显示像。 通过这样的步骤,就可以绘制出简单的了。在实际应用中,还可以通过设置各种参数,如点的大小、颜色、形状、标签等来使更加美观和易于阅读。 ### 回答3: Python是一种高级编程语言,常常用于数据分析和可视化。其中的Matplotlib提供了广泛的数据可视化功能。plt.plot()是Matplotlib中的一个函数,可以用来绘制。 首先,我们需要导入Matplotlib。通常使用plt别名引用它: ```python import matplotlib.pyplot as plt ``` 之后,如果我们想要绘制简单的,我们需要提供x轴和y轴数据。我们可以将x轴和y轴的数据分别存储在两个列表中: ```python x = [1, 2, 3, 4, 5] y = [2, 4, 6, 8, 10] ``` 然后,我们可以调用plt.scatter()函数来绘制: ```python plt.scatter(x, y) plt.show() ``` 该代码将绘制一个简单的,其中x轴的值为1到5,y轴的值为2到10: ![scatter-plot](https://lh6.googleusercontent.com/RL_bd_Ln0YPTL-KB1sU0EiVwpQbbTfBZCk4T2XkwaHJnmwVHdvrQjBPL7s_sgTBCdUsgqNgd766CYXgs-0Rjih1MZgXUpTr6yDvEKGa4weDymBYtgKHw3LXpCuPCFZy3Mhtqrh7f) 我们也可以自定义点的颜色和形状。例如,我们可以将所有的点设置为蓝色圆形: ```python plt.scatter(x, y, color='blue', marker='o') plt.show() ``` 我们还可以将点设置为不同的颜色和大小,以便突出不同的数据集。例如,下面的代码将绘制两个不同颜色和大小的数据点集: ```python import random # 创两个数据点集 x1 = [random.uniform(0, 1) for i in range(50)] y1 = [random.uniform(0, 1) for i in range(50)] x2 = [random.uniform(1, 2) for i in range(50)] y2 = [random.uniform(1, 2) for i in range(50)] # 绘制 plt.scatter(x1, y1, s=50, c='red', marker='o') plt.scatter(x2, y2, s=100, c='blue', marker='D') plt.show() ``` 该代码将绘制两个不同颜色和大小的,其中红色圆形数据点集位于x轴和y轴的范围为0到1的区域内,蓝色菱形数据点集位于x轴和y轴的范围为1到2的区域内: ![different-scatter-plot](https://lh5.googleusercontent.com/6_NerN0--lBcqSCCfVE_swL_0W1S-A0hAop38uJ_Fg7fxB31f7BSEz-mMS1DjiOh-H4Bqu9Fc90kZlnLkKf9MfuWj90rqAbZMO3qFbVq8x4_jGjvS5Pyk8HqLVArL-0MQbIGqvJ4) 总之,plt.plot()函数是Matplotlib中常用的函数之一,可以用于绘制。通过设置可选的参数,我们可以自定义点的形状、颜色和大小,以展示各种类型的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若oo尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值