首页 > 解决方案 > 如何在 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()

我试图关注这篇文章。但是,该帖子提出了不同的方案。interp1d到目前为止我正在使用,帖子建议使用interpolate. 我尝试转换我到目前为止所做的,但没有奏效。

我能做些什么?

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

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

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

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

提前致谢。

标签: python-3.xmatplotlibinterpolationnumerical-methodsderivative

解决方案


我更喜欢使用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

输出

在此处输入图像描述


推荐阅读