如何用Matplotlib与mendeleev自动添加垂直于电负性曲线的箭头
自动生成垂直于电负性曲线的箭头标注
我绘制了原子序数与Pauling电负性的关系曲线,希望基于mendeleev库提供的元素电负性值自动批量生成箭头标注,无需手动逐个编写,同时要求箭头垂直于曲线。当前已手动添加部分标注,需要实现自动化替换。
解决方案代码
from mendeleev import element import matplotlib.pyplot as plt import numpy as np # 获取元素数据,过滤电负性为空的元素 x = [] y = [] element_names = [] for i in range(1, 108): elem = element(i) en = elem.en_pauling if en is not None: x.append(i) y.append(en) element_names.append(elem.name) # 转换为numpy数组便于计算 x_np = np.array(x) y_np = np.array(y) plt.figure(figsize=(12, 7)) # 绘制电负性曲线 plt.plot(x_np, y_np, color='purple', marker='+', linestyle='-', label='Pauling电负性') # 设置图表基础属性 plt.xticks([0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 108]) plt.yticks([0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5]) plt.xlim(0, 108) plt.ylim(0, 5) plt.grid(True) plt.xlabel("原子序数 Z") plt.ylabel("Pauling电负性") plt.title("前108种元素的Pauling电负性变化趋势") plt.legend() # 计算曲线各点斜率(用于确定垂直方向) dy_dx = np.gradient(y_np, x_np) # 批量生成垂直箭头标注 for xi, yi, name, slope in zip(x_np, y_np, element_names, dy_dx): # 计算垂直于曲线的单位向量 if slope == 0: # 水平线段,垂直方向为竖直方向 dx, dy = 0, 0.3 else: norm = np.sqrt(1 + (1/slope)**2) dx = 1 / norm dy = (-1/slope) / norm # 控制标注文本的偏移距离 offset = 2.0 text_x = xi + dx * offset text_y = yi + dy * offset # 组装标注内容 annot_text = f"{name} EN={yi:.2f}" # 添加标注与箭头 plt.annotate(annot_text, xy=(xi, yi), xytext=(text_x, text_y), arrowprops={'facecolor': 'black', 'shrink': 0.05, 'width': 0.5}, fontsize=8) plt.savefig("En_pauling_auto.png", dpi=300) plt.show()
关键实现说明
- 数据过滤:自动跳过电负性为
None的元素(如部分惰性气体),避免绘图报错 - 垂直方向计算:通过
np.gradient获取曲线各点斜率,推导垂直切线的单位向量,确保箭头完全垂直于曲线 - 批量自动化:循环遍历所有有效元素,自动生成标注文本和箭头位置,无需手动编写每个标注
- 细节优化:处理斜率为0的特殊情况,统一标注偏移量,设置小字体避免文本重叠
内容的提问来源于stack exchange,提问作者Jojo
相关产品推荐
相关产品推荐

