2次元データの欠損箇所(nan値)の内挿


scipyinterpolateを使って2次元データの欠損値の内挿を行った。

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

np.random.seed(0)
#ランダムな値を持つ10x10の2次元データの作成
data = np.random.randint(0,100,size=(15,15)).astype(np.float64)
#画像のランダムな25箇所を欠損値に変換
nanind=np.random.choice(np.size(data), size=25)
data.reshape(-1)[nanind]=np.nan

#データのグリッド座標を取得
x, y = np.meshgrid(np.arange(data.shape[0]),
                   np.arange(data.shape[1]),
                   indexing = 'ij')

#欠損箇所のマスクを作成
ma_data = np.ma.masked_invalid(data)

#欠損していないデータのみを取得
val_x = x[~ma_data.mask]
val_y = y[~ma_data.mask]
val_data = data[~ma_data.mask]

#線形内挿
inp_line=interpolate.LinearNDInterpolator((val_x,val_y), val_data.ravel())
inp_line_data=inp_line((x,y))

#最近傍内挿
inp_near=interpolate.NearestNDInterpolator((val_x,val_y), val_data.ravel())
inp_near_data=inp_near((x,y))

#プロット
fig, ax=plt.subplots(1,3, figsize=(10,10))
datas=[data, inp_line_data, inp_near_data]
titles=['Original','Linear Inp','Nearest Inp']
for a,data, title  in zip(ax, datas, titles):
    a.imshow(data,cmap='jet')
    a.set_title(title)

結果

その他

np.nanの箇所のマスクをつくるときmask=(data==np.nan)はダメ。
np.nan==np.nanFalse
np.nan is np.nanTrueですが、data is np.nanはデータ全体とnp.nanの比較なのでFalse
np.ma.masked_invalid を使いましょう。