Using scipy.ndimage, your problem can be solved with nearest neighbor interpolation in 2 lines :
from scipy import ndimage as nd
indices = nd.distance_transform_edt(invalid_cell_mask, return_distances=False, return_indices=True)
data = data[tuple(ind)]
Now, in the form of a function:
import numpy as np
from scipy import ndimage as nd
def fill(data, invalid=None):
"""
Replace the value of invalid 'data' cells (indicated by 'invalid')
by the value of the nearest valid data cell
Input:
data: numpy array of any dimension
invalid: a binary array of same shape as 'data'.
data value are replaced where invalid is True
If None (default), use: invalid = np.isnan(data)
Output:
Return a filled array.
"""
if invalid is None: invalid = np.isnan(data)
ind = nd.distance_transform_edt(invalid,
return_distances=False,
return_indices=True)
return data[tuple(ind)]
Exemple of use:
def test_fill(s,d):
# s is size of one dimension, d is the number of dimension
data = np.arange(s**d).reshape((s,)*d)
seed = np.zeros(data.shape,dtype=bool)
seed.flat[np.random.randint(0,seed.size,int(data.size/20**d))] = True
return fill(data,-seed), seed
import matplotlib.pyplot as plt
data,seed = test_fill(500,2)
data[nd.binary_dilation(seed,iterations=2)] = 0 # draw (dilated) seeds in black
plt.imshow(np.mod(data,42)) # show cluster
result:
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…