您已经非常接近了,但似乎您将"x"和"y"的概念在脑中混淆了。观察您提供的图表,您怎么能期望这样的数据通过曲线拟合呢?因为根据这个图,对于单一的$C_D$值,存在多个可能的$C_L$值,这违反了函数映射的基本原则。
从您的函数来看,它似乎是根据$C_L$值预测$C_D$值的,因此在这种情况下,"x"应该是升力系数($C_L$),而"y"是阻力系数($C_D$)。如果将两者的位置互换,并使用curve_fit
函数,按照正确的变量顺序进行操作,问题就能得到解决。我使用您提供的系数数据进行了尝试,代码和生成的图表如下所示:
# 复制您提供的数据,但请注意,您最后两个数据点有些异常(可能是误差较大的离群点,或者数据输入有误,也可能是顺序颠倒了)
CL = np.array([-0.2863876, -0.15198764, -0.00709039, 0.1414652, 0.28727075, 0.43092027,
0.57339435, 0.71901446, 0.95383017, 1.00155515, 1.04740696, 0.93310272])
CD = np.array([-0.02768897, -0.03168675, -0.03116817, -0.02166403, -0.00677296, 0.01566423,
0.04477065, 0.08153319, 0.16150749, 0.19508941, 0.21802003, 0.12811101])
def test_func(CL, k, CD_0):
return k*(CL**2) + CD_0 # 您的测试函数,根据CL(x)预测CD(y)
popt, pcov = curve_fit(test_func, CL, CD, p0=[1., 0.01]) # 注意这里CL作为第一个参数,因为它是我们关注的"x"变量,CD作为拟合目标"y"
# 绘制结果
plt.scatter(CL, CD, marker="x", label="数据", c="dodgerblue")
CL_model = np.linspace(np.min(CL), np.max(CL), 100)
CD_model = test_func(CL_model, *popt)
plt.plot(CL_model, CD_model, label=rf"模型: k = {popt[0]:.2f}, $CD_0$ = {popt[1]:.2f}", c="orange")
plt.legend()
plt.xlabel(r"$C_L$")
plt.ylabel(r"$C_D$")
plt.show()
但是,正如@JJacquelin在其回答中指出的那样,您可能需要考虑更改用于拟合数据的函数形式。选择形如$y = x2 + c$的函数意味着曲线的最小值必须正好位于$x = 0$处,然而您的数据显示情况并非如此。同时,您应当检查数据,并剔除任何不符合此类模型物理合理性的数据点。