web-dev-qa-db-ja.com

Python-scipy / numpy / pandasの二次微分

pythonの2つの導関数をデータの2つの派手な配列で取得しようとしています。

たとえば、問題の配列は次のようになります。

_import numpy as np

x = np.array([ 120. ,  121.5,  122. ,  122.5,  123. ,  123.5,  124. ,  124.5,
        125. ,  125.5,  126. ,  126.5,  127. ,  127.5,  128. ,  128.5,
        129. ,  129.5,  130. ,  130.5,  131. ,  131.5,  132. ,  132.5,
        133. ,  133.5,  134. ,  134.5,  135. ,  135.5,  136. ,  136.5,
        137. ,  137.5,  138. ,  138.5,  139. ,  139.5,  140. ,  140.5,
        141. ,  141.5,  142. ,  142.5,  143. ,  143.5,  144. ,  144.5,
        145. ,  145.5,  146. ,  146.5,  147. ])

y = np.array([  1.25750000e+01,   1.10750000e+01,   1.05750000e+01,
         1.00750000e+01,   9.57500000e+00,   9.07500000e+00,
         8.57500000e+00,   8.07500000e+00,   7.57500000e+00,
         7.07500000e+00,   6.57500000e+00,   6.07500000e+00,
         5.57500000e+00,   5.07500000e+00,   4.57500000e+00,
         4.07500000e+00,   3.57500000e+00,   3.07500000e+00,
         2.60500000e+00,   2.14500000e+00,   1.71000000e+00,
         1.30500000e+00,   9.55000000e-01,   6.65000000e-01,
         4.35000000e-01,   2.70000000e-01,   1.55000000e-01,
         9.00000000e-02,   5.00000000e-02,   2.50000000e-02,
         1.50000000e-02,   1.00000000e-02,   1.00000000e-02,
         1.00000000e-02,   1.00000000e-02,   1.00000000e-02,
         1.00000000e-02,   1.00000000e-02,   5.00000000e-03,
         5.00000000e-03,   5.00000000e-03,   5.00000000e-03,
         5.00000000e-03,   5.00000000e-03,   5.00000000e-03,
         5.00000000e-03,   5.00000000e-03,   5.00000000e-03,
         5.00000000e-03,   5.00000000e-03,   5.00000000e-03,
         5.00000000e-03,   5.00000000e-03])
_

現在はf(x) = yがあり、_d^2 y / dx^2_が必要です。

数値的には、関数を内挿して導関数を分析的に取得するか、 高次有限差分 を使用できることを知っています。どちらか一方をより速く、より正確に考えれば、どちらかを使用するのに十分なデータがあると思います。

np.interp()と_scipy.interpolate_を確認しましたが、これはフィットした(線形または3次)スプラインを返しますが、その時点で微分を取得する方法がわかりません。

どんなガイダンスも大歓迎です。

12
Jared

Scipyの1-D Splines 関数を使用してデータを補間できます。計算されたスプラインには、導関数を計算するための便利なderivativeメソッドがあります。

例のデータの場合、UnivariateSplineを使用すると、次の近似が得られます

import matplotlib.pyplot as plt
from scipy.interpolate import UnivariateSpline

y_spl = UnivariateSpline(x,y,s=0,k=4)

plt.semilogy(x,y,'ro',label = 'data')
x_range = np.linspace(x[0],x[-1],1000)
plt.semilogy(x_range,y_spl(x_range))

enter image description here

少なくとも視覚的には、フィット感はかなり良いようです。 UnivariateSplineで使用されるパラメーターを試してみるとよいでしょう。

スプラインフィットの2番目の導関数は、次のように簡単に取得できます。

y_spl_2d = y_spl.derivative(n=2)

plt.plot(x_range,y_spl_2d(x_range))

enter image description here

結果はやや不自然に見えます(データが物理的なプロセスに対応している場合)。スプラインフィットのパラメーターを変更するか、データを改善する(たとえば、サンプルを増やす、ノイズの少ない測定を実行する)か、分析関数を決定してデータをモデル化し、カーブフィットを実行する(たとえば、sicpyの curve_fit

12
Stelios

有限差分により、配列上のxの各平均値に対するyの1次導関数は、次のようになります。

dy=np.diff(y,1)
dx=np.diff(x,1)
yfirst=dy/dx

そして、xの対応する値は次のとおりです。

xfirst=0.5*(x[:-1]+x[1:])

2番目の注文については、同じプロセスをもう一度実行します。

dyfirst=np.diff(yfirst,1)
dxfirst=np.diff(xfirst,1)
ysecond=dyfirst/dxfirst

xsecond=0.5*(xfirst[:-1]+xfirst[1:])
5
manu190466