web-dev-qa-db-ja.com

python / scipyの多変量スプライン補間?

Pythonで多変量スプライン補間を実装するためのライブラリモジュールまたは他の簡単な方法はありますか?

具体的には、一定間隔の3次元グリッド上にスカラーデータのセットがあり、ドメイン全体に散在する少数のポイントで補間する必要があります。 2次元の場合、私は scipy.interpolate.RectBivariateSpline を使用しており、基本的に3次元データへの拡張を探しています。

私が見つけたN次元補間ルーチンは十分ではありません:滑らかさのために LinearNDInterpolator よりもスプラインを好むでしょう、そして私は例えば、のために非常に多くのデータポイント(しばしば100万を超える)を持っています動作する放射基底関数。

これを実行できるpythonライブラリ、または私が呼び出したり移植したりできる別の言語のライブラリを知っている人がいたら、本当にありがたいです。

27
Chris P

私があなたの質問を正しく理解している場合、あなたの入力「観測」データは定期的にグリッド化されていますか?

もしそうなら、 scipy.ndimage.map_coordinates はまさにあなたが望むことをします。

最初のパスで理解するのは少し難しいですが、基本的には、ピクセル/ボクセル/ n次元インデックス座標でグリッドの値を補間する一連の座標をフィードするだけです。

2Dの例として:

import numpy as np
from scipy import ndimage
import matplotlib.pyplot as plt

# Note that the output interpolated coords will be the same dtype as your input
# data.  If we have an array of ints, and we want floating point precision in
# the output interpolated points, we need to cast the array as floats
data = np.arange(40).reshape((8,5)).astype(np.float)

# I'm writing these as row, column pairs for clarity...
coords = np.array([[1.2, 3.5], [6.7, 2.5], [7.9, 3.5], [3.5, 3.5]])
# However, map_coordinates expects the transpose of this
coords = coords.T

# The "mode" kwarg here just controls how the boundaries are treated
# mode='nearest' is _not_ nearest neighbor interpolation, it just uses the
# value of the nearest cell if the point lies outside the grid.  The default is
# to treat the values outside the grid as zero, which can cause some Edge
# effects if you're interpolating points near the Edge
# The "order" kwarg controls the order of the splines used. The default is 
# cubic splines, order=3
zi = ndimage.map_coordinates(data, coords, order=3, mode='nearest')

row, column = coords
nrows, ncols = data.shape
im = plt.imshow(data, interpolation='nearest', extent=[0, ncols, nrows, 0])
plt.colorbar(im)
plt.scatter(column, row, c=zi, vmin=data.min(), vmax=data.max())
for r, c, z in Zip(row, column, zi):
    plt.annotate('%0.3f' % z, (c,r), xytext=(-10,10), textcoords='offset points',
            arrowprops=dict(arrowstyle='->'), ha='right')
plt.show()

enter image description here

これをn次元で行うには、適切なサイズの配列を渡す必要があります。

import numpy as np
from scipy import ndimage

data = np.arange(3*5*9).reshape((3,5,9)).astype(np.float)
coords = np.array([[1.2, 3.5, 7.8], [0.5, 0.5, 6.8]])
zi = ndimage.map_coordinates(data, coords.T)

スケーリングとメモリ使用量に関する限り、1より大きい次数を使用している場合(つまり、線形補間ではない場合)、map_coordinatesは配列のフィルター処理されたコピーを作成します。非常に少数のポイントで補間するだけの場合、これはかなり大きなオーバーヘッドになります。ただし、補間するポイントの数に応じて増加することはありません。入力データ配列の単一の一時コピーに十分なRAMがある限り、問題はありません。

データのコピーをメモリに保存できない場合は、a)prefilter=Falseorder=1を指定して線形補間を使用するか、b)ndimage.spline_filterを使用して元のデータをフィルター処理されたバージョンに置き換えてから、map_coordinatesをprefilter=Falseで呼び出すことができます。

十分なRAMがある場合でも、map_coordinatesを複数回呼び出す必要がある場合(インタラクティブな使用など)、フィルター処理されたデータセットを維持することは大幅なスピードアップになります。

43
Joe Kington

Dim> 2での平滑スプライン補間は実装が難しいため、それを実行できる無料で利用できるライブラリは多くありません(実際、私にはわかりません)。

逆距離加重補間を試すことができます。以下を参照してください。 Pythonを使用した逆距離加重(IDW)補間 。これにより、適度にスムーズな結果が得られ、RBFよりも大きなデータセットへのスケーリングが向上します。

2
pv.