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

时间:2018-09-08 18:03:59

标签: python-3.x matplotlib interpolation numerical-methods derivative

我正在使用Python 3进行与数值分析有关的任务。

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

因此,这些任务已完成。输出的图片很棒,并且代码可以正常工作。 但是,我需要检查三次样条的导数是否看起来像余弦函数。

看看这张图片:

enter image description here

以橙色显示余弦函数。以蓝色显示正弦函数。用红色表示我采样的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,而该帖子建议使用interpolate。我尝试转换到目前为止的操作,但是没有用。

我该怎么办?

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

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

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

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

谢谢。

2 个答案:

答案 0 :(得分:1)

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

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

n

输出

enter image description here

答案 1 :(得分:1)

其他软件包或函数当然可能更方便,但为理解起见,您可以自己计算导数(dy / dx)并将其绘制出来。

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

添加此行将导致

enter image description here

其中红线是f2的派生词。