python matplotlib:如何在曲线上添加一个点标记,只知道x值?

python matplotlib:如何在曲线上添加一个点标记,只知道x值?,python,matplotlib,Python,Matplotlib,例如,在matplotlib中,我基于几个点绘制了一条简单曲线: from matplotlib import pyplot as plt import numpy as np x=[0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2. , 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8

例如,在matplotlib中,我基于几个点绘制了一条简单曲线:

from matplotlib import pyplot as plt
import numpy as np

x=[0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1, 1.2,
       1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2. , 2.1, 2.2, 2.3, 2.4, 2.5,
       2.6, 2.7, 2.8, 2.9]
y=[0.0, 0.19, 0.36, 0.51, 0.64, 0.75, 0.8400000000000001, 0.91, 0.96, 0.99, 1.0, 
   0.99, 0.96, 0.9099999999999999, 0.8399999999999999, 0.75, 0.6399999999999997, 
   0.5099999999999998, 0.3599999999999999, 0.18999999999999995, 0.0, 
   -0.20999999999999996, -0.4400000000000004, -0.6900000000000004, 
   -0.9600000000000009, -1.25, -1.5600000000000005, -1.8900000000000006, 
   -2.240000000000001, -2.610000000000001]

plt.plot(x,y)
plt.show()

假设我想高亮显示曲线上x值为0.25的点,但我不知道该点的y值。我应该怎么做?

您可以手动执行如下线性插值:

def get_y_val(p):
    lower_i = max(i for (i, v) in enumerate(x) if v<= p)
    upper_i = min(i for (i, v) in enumerate(x) if v>= p)
    d = x[upper_i] - x[lower_i]
    if d == 0:
        return y[lower_i]
    y_pt = y[lower_i] * (x[upper_i] - p) / d+ y[upper_i] * (p - 
    x[lower_i]) / d
    return y_pt
def get_y_val(p):
下_i=max(如果v=p,枚举(x)中(i,v)的i)
d=x[上下]x[下]
如果d==0:
返回y[下_i]
y_pt=y[lower_i]*(x[upper_i]-p)/d+y[upper_i]*(p-
x[下i])/d
返回y\u pt

最简单的解决方案是对提供的x值在相邻点之间执行线性插值。下面是一个示例代码,用于说明一般原则:

X=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2,
   1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2. , 2.1, 2.2, 2.3, 2.4, 2.5,
   2.6, 2.7, 2.8, 2.9]
Y=[0.0, 0.19, 0.36, 0.51, 0.64, 0.75, 0.8400000000000001, 0.91, 0.96,
   0.99, 1.0, 0.99, 0.96, 0.9099999999999999, 0.8399999999999999, 0.75,
   0.6399999999999997, 0.5099999999999998, 0.3599999999999999,
   0.18999999999999995, 0.0, -0.20999999999999996, -0.4400000000000004,
   -0.6900000000000004, -0.9600000000000009, -1.25, -1.5600000000000005,
   -1.8900000000000006, -2.240000000000001, -2.610000000000001]

def interpolate(X, Y, xval):
    for n, x in enumerate(X):
        if x > xval: break
    else: return None # xval > last x value
    if n == 0: return None # xval < first x value
    xa, xb = X[n-1], X[n] # get surrounding x values
    ya, yb = Y[n-1], Y[n] # get surrounding y values
    if xb == xa: return ya # 
    return ya + (xval - xa) * (yb - ya) / (xb - xa) # compute yval by interpolation

print(interpolate(X, Y, 0.25)) # --> 0.435 
print(interpolate(X, Y, 0.85)) # --> 0.975
print(interpolate(X, Y, 2.15)) # --> -0.3259999999999997
print(interpolate(X, Y, -1.0)) # --> None (out of bounds)
print(interpolate(X, Y, 3.33)) # --> None (out of bounds)
X=[0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0,1.1,1.2,
1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2. , 2.1, 2.2, 2.3, 2.4, 2.5,
2.6, 2.7, 2.8, 2.9]
Y=[0.0,0.19,0.36,0.51,0.64,0.75,0.8400000000000001,0.91,0.96,,
0.99, 1.0, 0.99, 0.96, 0.9099999999999999, 0.8399999999999999, 0.75,
0.6399999999999997, 0.5099999999999998, 0.3599999999999999,
0.18999999999999995, 0.0, -0.20999999999999996, -0.4400000000000004,
-0.6900000000000004, -0.9600000000000009, -1.25, -1.5600000000000005,
-1.8900000000000006, -2.240000000000001, -2.610000000000001]
def插值(X,Y,xval):
对于枚举(x)中的n,x:
如果x>xval:中断
else:返回None#xval>最后一个x值
如果n==0:返回None#xval<第一个x值
xa,xb=X[n-1],X[n]#获取周围的X值
ya,yb=Y[n-1],Y[n]#获取周围的Y值
如果xb==xa:返回ya#
返回ya+(xval-xa)*(yb-ya)/(xb-xa)#通过插值计算yval
打印(内插(X,Y,0.25))#-->0.435
打印(内插(X,Y,0.85))#-->0.975
打印(内插(X,Y,2.15))#-->-0.325999997
打印(内插(X,Y,-1.0))#-->无(超出范围)
打印(内插(X,Y,3.33))#-->无(超出范围)

注意:当提供的
xval
不在x值范围内时,函数返回
None

良好点。我没有意识到默认情况下pyplot使用线性插值,曲线在我看来非常平滑。但当我再次尝试使用更少、更稀疏的点时,我发现这是线性插值。