pythonarraysnumpypointspatial-interpolation

Vectorized method to insert arrays of different length at different spots in an ndarray


I'm trying to "expand" a 2D numpy array nadir of points (x,y,z), and fill gaps in space with interpolated points. Where there exist spatial gaps bigger than some tolerance dist, I want to use np.insert to insert the required number of nan rows to fill that gap, adding nan points to be interpolated after.

First, I locate the gaps, and see how many points (rows) I need to insert in each gap to achieve the desired spatial point density:

import numpy as np

# find and measure gaps
nadir = nadir[~np.isnan(nadir).any(axis = 1)]
dist = np.mean(np.linalg.norm(np.diff(nadir[:,0:2], axis = 0), axis = 1), axis = 0) # mean distance for gap definition
gaps = np.where(np.linalg.norm(np.diff(nadir[:,0:2], axis = 0), axis = 1) > dist)[0] # gap locations
sizes = (np.linalg.norm(np.diff(nadir[:,0:2], axis = 0), axis = 1)[gaps] // dist).astype(int) # how many points to insert in each gap

What I wish I could do is pass a list of ndarrays to np.insert() for the values argument, like this:

nadir = np.insert(nadir, gaps, [np.full((size, 3), np.nan) for size in sizes], axis = 0)

such that at every index in gaps, the corresponding nan array of shape (size,3) gets inserted. But the above code doesn't work:

"ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (616,) + inhomogeneous part."

I could achieve this in a loop, but a nice vectorized approach would be ideal. Any ideas? Again, my final goal is to spatial fill gaps in this 3D data with interpolated values, without gridding, so any other clever approaches would also work!


Solution

  • To insert multiple rows, the number of indices has to match the number of rows:

    In [176]: x=np.arange(12).reshape(4,3)
    
    In [177]: np.insert(x,[1,1,1,2,2,3],np.ones((6,3),int)+100,axis=0)
    Out[177]: 
    array([[  0,   1,   2],
           [101, 101, 101],
           [101, 101, 101],
           [101, 101, 101],
           [  3,   4,   5],
           [101, 101, 101],
           [101, 101, 101],
           [  6,   7,   8],
           [101, 101, 101],
           [  9,  10,  11]])