如何在 Python 3 中绘制三次样条的导数?

How to plot the derivative of a Cubic spline in Python 3?

我正在使用 Python 3 来完成与数值分析相关的任务。

我必须绘制一些源自正弦函数的点。此外,我需要对这些点进行三次插值(三次样条)。

这样,这些任务就完成了。输出图片很棒,代码有效。 但是,我需要检查三次样条的导数是否像余弦函数。

看看这张图片:

在橙色中,您会看到余弦函数。在蓝色中,您会看到正弦函数。红色部分是我采样的 5 个点。在紫色中,您可以看到线性插值。并且,在破折号中,您会看到三次插值。

我需要绘制虚线曲线的导数并将其与橙色曲线进行比较。

凭直觉,我知道它们会非常相似。但是,我无法用图表证明

这是代码:

import math
import random
from numpy import array 
import numpy as np 
import matplotlib.pyplot as plot
from scipy.interpolate import interp1d
from scipy import interpolate
from scipy.misc import derivative as deriv

def random_sine():

    lista_f_x = []
    lista_x = []

    for i in range(1,6):

        aleatorio = random.uniform(0,360)
        aleatorio = math.radians(aleatorio)
        lista_x.append(aleatorio)

        sine_random = math.sin(aleatorio)
        lista_f_x.append(sine_random)

    lista_x = array(lista_x)
    lista_f_x = array(lista_f_x)

    return ("x",lista_x,"f(x)", lista_f_x) 

# para ter um grupo controle melhor, deixe esses valores aleatórios, gerados uma vez, como fixos
fixed_x = array([5.80990031, 1.7836885,  4.62073799, 0.89337425, 5.62219906])
fixed_y = array([-0.45581264,  0.97742392, -0.99580299,  0.77919112, -0.61389568])

x = fixed_x
y = fixed_y

"""
caso deseje usar os valores fixos
basta inserir o comentário "#" nas linhas
39, 40 e 41 abaixo
"""
#teste_dinamico = random_sine()
#x = teste_dinamico[1]
#y = teste_dinamico[3]

time = np.arange(0,10,0.1)

amplitude = np.sin(time)

amplitude_cosine = np.cos(time)

plot.plot(time, amplitude, time, amplitude_cosine)

plot.title('Função Seno')

plot.xlabel('Coordenadas de X')

plot.ylabel('Seno(x)')

plot.grid(True, which='both')

plot.axhline(y=0, color='k')

pares_x_y = list(zip(x,y))

sort_pares_x_y = sorted(pares_x_y)

x_ordenado = []
y_ordenado_simetric = []

for i in sort_pares_x_y:

    x_ordenado.append(i[0])
    y_ordenado_simetric.append(i[1])

x_ordenado = array(x_ordenado)
y_ordenado_simetric = array(y_ordenado_simetric)

f = interp1d(x_ordenado, y_ordenado_simetric)

f2 = interp1d(x_ordenado, y_ordenado_simetric, kind="cubic")

plot.plot(x_ordenado, f2(x_ordenado))

minimo = min(x_ordenado)
maximo = max(x_ordenado)

xnew = np.linspace(minimo, maximo, num=400, endpoint=True)

plot.plot(x_ordenado, y_ordenado_simetric, 'o', xnew, f(xnew), '-', xnew, f2(xnew), '--')

plot.scatter(x,y)

plot.show()

我试图遵循这个 。但是,post 建议使用不同的包。到目前为止,我正在使用 interp1d,post 建议使用 interpolate。我尝试转换我目前所做的,但没有成功。

我能做什么?

如果我用 matplotlib 绘制曲线,是否有更简单的方法来绘制曲线的导数?

解决这个问题的最佳策略是什么?

1 - 我应该再试一次并将所有内容更改为 SO 上建议的其他包吗?

2 - 我应该使用一些数值方法进行微分吗?

提前致谢。

我更愿意使用 interpolate.splev 而不是 interp1d 因为除了提供插值外,前者还允许仅通过一个简单的参数 der=n 轻松计算导数,其中 n是导数的阶数。我只需要对您的代码进行 次要 更改即可使事情正常进行。

下面我只显示 相关的 行代码,我 added/modified (通过评论突出显示)并附上结果图。红色虚线是所需的导数,可与余弦函数相媲美。

f2 = interpolate.splrep(x_ordenado, y_ordenado_simetric) # Added

minimo = min(x_ordenado)
maximo = max(x_ordenado)

xnew = np.linspace(minimo, maximo, num=400, endpoint=True)
ynew = interpolate.splev(xnew, f2) # Added 
ynew_der = interpolate.splev(xnew, f2, der=1) # Added to compute first derivative

plot.plot(x_ordenado, y_ordenado_simetric, 'o', xnew, f(xnew), '-', xnew, ynew, '--') # Modified
plot.plot(xnew, ynew_der, '--r') # Derivative Added

输出

其他包或函数当然可能更顺手,但为了理解,您可以简单地自己计算导数(dy/dx)并绘制它。

plot.plot(xnew[:-1], np.diff(f2(xnew))/np.diff(xnew), color="red")

添加这一行将导致

其中红线是f2的导数。