如何在Matplotlib绘图中查找并显示特定坐标点?
问题
我用plt.plot(xdata,ydata)绘制了一幅图,希望找到y坐标等于125.94937644205281 + 1(卡方值+1)时对应的x坐标,并将该点在图中显示出来。尝试过找根法,但寻找满足卡方+1的参数耗时极久,代码还陷入了无限循环。如果Matplotlib没有直接查找图中特定点的方法,应该选择哪种求解器?如何使用?
附上我尝试的代码:
target = chisq_min + 1 def target_chisq_plus1 (gradient): return chisq([gradient], xval, yval, yerr) - target # 寻找根 initials = [(a_soln, 0.0121320), (0.0122193, a_soln)] # <- 导致卡方值+1的两个参数初始边界 tolerance = 0.01 chisquard_plus_one_solutions = [] while True: for initial in initials: if target_chisq_plus1(initial[0]) > 0: xp = initial[0] xn = initial[1] else: xp = initial[1] xn = initial[0] next_approximation = (xp + xn) / 2 if target_chisq_plus1(next_approximation) > 0: xp = next_approximation else: xn = next_approximation if abs(target_chisq_plus1(next_approximation)) < tolerance: gradient_solutions.append((next_approximation, chisq([next_approximation], xval, yval, yerr))) break
解决方案
1. 用SciPy专业求解器替代手动二分法
你手动实现的二分法存在逻辑漏洞(比如while True无终止条件,极易无限循环),直接用SciPy内置的求解器更高效可靠,推荐scipy.optimize.bisect或root_scalar,二者都是专门针对单变量函数找根的工具:
示例代码(bisect版本)
from scipy.optimize import bisect import matplotlib.pyplot as plt # 保留你的目标值与目标函数 target = chisq_min + 1 def target_chisq_plus1(gradient): return chisq([gradient], xval, yval, yerr) - target gradient_solutions = [] # 遍历每个初始边界对求解 for lower, upper in initials: # bisect要求区间两端函数值符号相反,先做校验 if target_chisq_plus1(lower) * target_chisq_plus1(upper) >= 0: print(f"区间[{lower}, {upper}]两端函数值符号相同,无法用bisect求解") continue # 执行求解,设置精度阈值 sol = bisect(target_chisq_plus1, lower, upper, xtol=0.01) gradient_solutions.append((sol, chisq([sol], xval, yval, yerr)))
选择SciPy求解器的优势
- 自带收敛判断与终止条件,不会陷入无限循环
- 经过底层优化,求解速度远快于手动实现的二分法
- 严谨处理边界异常情况,避免无效计算
2. 在Matplotlib图中标注目标点
找到x坐标后,用plt.scatter标记点,搭配plt.annotate添加坐标标注:
# 先绘制原始曲线 plt.plot(xdata, ydata, label='原始曲线') # 遍历所有解,逐个标注 for x_sol, y_sol in gradient_solutions: # 红色标记目标点,zorder确保点在曲线上方 plt.scatter(x_sol, y_sol, color='red', s=50, zorder=5) # 添加坐标文本,偏移位置避免遮挡 plt.annotate(f'({x_sol:.4f}, {y_sol:.4f})', xy=(x_sol, y_sol), xytext=(x_sol+0.0001, y_sol+2), fontsize=10) plt.xlabel('X轴') plt.ylabel('Y轴(卡方值)') plt.legend() plt.show()
3. 额外提示
- 若
chisq是多变量函数,需要找二维卡方+1等高线,可改用scipy.optimize.root或scipy.optimize.minimize来寻找满足条件的参数组合 - 初始区间尽量缩小合理范围,能大幅提升求解效率
内容的提问来源于stack exchange,提问作者D Son
相关产品推荐
相关产品推荐

