2013-03-18 1 views
7

ScipyのRectBivariateSplineクラスを使用して、グリッド化されたwindstressのデータを定期的に補間しようとしています。いくつかのグリッドポイントでは、入力データに無効なデータエントリが含まれており、NaN値に設定されています。まず、二次元補間で解をScott's questionに使用しました。私のデータを使って、補間はNaNだけを含む配列を返します。データが構造化されておらず、SmoothBivariateSplineクラスを使用していると仮定して、別のアプローチを試みました。どうやら、データ配列の形状が(719 x 2880)なので、構造化されていない補間を使用するにはあまりにも多くのデータ点があります。NaN値またはマスクを使用した大規模配列の2変数式構造補間

from __future__ import division 
import numpy 
import pylab 

from scipy import interpolate 


# The signal and lots of noise 
M, N = 20, 30 # The shape of the data array 
y, x = numpy.mgrid[0:M+1, 0:N+1] 
signal = -10 * numpy.cos(x/50 + y/10)/(y + 1) 
noise = numpy.random.normal(size=(M+1, N+1)) 
z = signal + noise 


# Some holes in my dataset 
z[1:2, 0:2] = numpy.nan 
z[1:2, 9:11] = numpy.nan 
z[0:1, :12] = numpy.nan 
z[10:12, 17:19] = numpy.nan 


# Interpolation! 
Y, X = numpy.mgrid[0.125:M:0.5, 0.125:N:0.5] 
sp = interpolate.RectBivariateSpline(y[:, 0], x[0, :], z) 
Z = sp(Y[:, 0], X[0, :]) 

sel = ~numpy.isnan(z) 
esp = interpolate.SmoothBivariateSpline(y[sel], x[sel], z[sel], 0*z[sel]+5) 
eZ = esp(Y[:, 0], X[0, :]) 


# Comparing the results 
pylab.close('all') 
pylab.ion() 

bbox = dict(edgecolor='w', facecolor='w', alpha=0.9) 
crange = numpy.arange(-15., 16., 1.) 

fig = pylab.figure() 
ax = fig.add_subplot(1, 3, 1) 
ax.contourf(x, y, z, crange) 
ax.set_title('Original') 
ax.text(0.05, 0.98, 'a)', ha='left', va='top', transform=ax.transAxes, 
    bbox=bbox) 

bx = fig.add_subplot(1, 3, 2, sharex=ax, sharey=ax) 
bx.contourf(X, Y, Z, crange) 
bx.set_title('Spline') 
bx.text(0.05, 0.98, 'b)', ha='left', va='top', transform=bx.transAxes, 
    bbox=bbox) 

cx = fig.add_subplot(1, 3, 3, sharex=ax, sharey=ax) 
cx.contourf(X, Y, eZ, crange) 
cx.set_title('Expected') 
cx.text(0.05, 0.98, 'c)', ha='left', va='top', transform=cx.transAxes, 
    bbox=bbox) 

次のような結果が得られます:Bivariate gridding. (a) The original constructed data, (b) Scipy's RectBivariateSpline and (c) SmoothBivariateSpline classes.

の図は、構成されたデータマップ(a)とscipyのダウンロードのRectBivariateSpline(Bを使用して結果を示して、私は次のスクリプトを作成した私の問題を説明するために

)とSmoothBivariateSpline(c)クラスを使用します。最初の補間では、NaNのみを持つ配列になります。理想的には、第2の補間に似た結果が予想されますが、これはより計算量が多くなります。私は必ずしもドメイン領域外のデータ補外を必要としません。

+1

データが欠落している構造化補間はできません。構造化されていない補間もオプションでない場合は、ドメインを長方形の塊に分割し、欠落しているデータがあればどこでも構造化されていない補間を行い、他のすべての構造化することができます。線形補間を使用していた場合は、ドメインの分割が唯一の問題になります。しかし、3次スプラインを使用している場合は、チャンク間の境界条件を処理する必要があります。これはどのように進むべきかわかりません。 – Jaime

+0

また、 'scipy.interpolate.griddata'にはsmoothbivariatesplineと同様に撮影することができます。 –

答えて

0

griddataを使用できます。唯一の問題は、エッジをうまく処理できないことです。

from __future__ import division 
import numpy 
import pylab 
from scipy import interpolate 


# The signal and lots of noise 
M, N = 20, 30 # The shape of the data array 
y, x = numpy.mgrid[0:M+1, 0:N+1] 
signal = -10 * numpy.cos(x/50 + y/10)/(y + 1) 
noise = numpy.random.normal(size=(M+1, N+1)) 
z = signal + noise 


# Some holes in my dataset 
z[1:2, 0:2] = numpy.nan 
z[1:2, 9:11] = numpy.nan 
z[0:1, :12] = numpy.nan 
z[10:12, 17:19] = numpy.nan 

zi = numpy.vstack((z[::-1,:],z)) 
zi = numpy.hstack((zi[:,::-1], zi)) 
y, x = numpy.mgrid[0:2*(M+1), 0:2*(N+1)] 
y *= 5 # anisotropic interpolation if needed. 

zi = interpolate.griddata((y[~numpy.isnan(zi)], x[~numpy.isnan(zi)]), 
       zi[~numpy.isnan(zi)], (y, x), method='cubic') 
zi = zi[:(M+1),:(N+1)][::-1,::-1] 

pylab.subplot(1,2,1) 
pylab.imshow(z, origin='lower') 
pylab.subplot(1,2,2) 
pylab.imshow(zi, origin='lower') 
pylab.show() 

あなたはメモリが不足した場合、あなたはの線に沿って、あなたのデータを分割することもできます:

これはここでは例です ...あなたのデータがどのように応じて、反映例えばによって助けすることができ
def large_griddata(data_x, vals, grid, method='nearest'): 
    x, y = data_x 
    X, Y = grid 
    try: 
     return interpolate.griddata((x,y),vals,(X,Y),method=method) 
    except MemoryError: 
     pass 

    N = (np.min(X)+np.max(X))/2. 
    M = (np.min(Y)+np.max(Y))/2. 

    masks = [(x<N) & (y<M), 
      (x<N) & (y>=M), 
      (x>=N) & (y<M), 
      (x>=N) & (y>=M)] 

    grid_mask = [(X<N) & (Y<M), 
      (X<N) & (Y>=M), 
      (X>=N) & (Y<M), 
      (X>=N) & (Y>=M)] 

    Z = np.zeros_like(X) 
    for i in range(4): 
     Z[grid_mask[i]] = large_griddata((x[masks[i]], y[masks[i]]), 
        vals[masks[i]], (X[grid_mask[i]], Y[grid_mask[i]]), method=method) 

    return Z