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

Ped*_*ino 1 interpolation matplotlib numerical-methods derivative python-3.x

我正在使用 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()
Run Code Online (Sandbox Code Playgroud)

我试着关注这个帖子。但是,该帖子建议使用不同的软件包。interp1d到目前为止我正在使用并且该帖子建议使用interpolate. 我尝试转换到目前为止所做的工作,但没有奏效。

我能做什么?

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

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

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

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

提前致谢。

She*_*ore 5

我更喜欢使用interpolate.splev而不是interp1d因为除了提供插值外,前者还允许使用一个简单的参数轻松计算导数,der=n其中n是导数的顺序。我只需要对你的代码做一些小的改动就可以使事情正常进行。

下面我只显示了我添加/修改的相关代码行(由注释突出显示),并附上了结果图。红色虚线是与余弦函数相当的所需导数。

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
Run Code Online (Sandbox Code Playgroud)

输出

在此处输入图片说明