I am struggling to perform a conceptually simple algorithm using optimized numpy vectorized operations. In the code below I have data
which is an array with a bunch of values, and coords
of which entry i
contains 3D spatial coordinates corresponding to data[i]
. I want to populate the array max_data
so that entry max_data[i,j,k]
is the maximum of all entries of data
such that the corresponding entries of coords
fall in the range [ [i,i+1], [j,j+1], [k,k+1] ]
. Example code that generates the data and implements the algorithm is below.
Is there any way to speed this up using numpy vectorized operations? I am running a version of this on arrays with ndata ~ 1e9 and it takes forever. I am not opposed to using other python libs.
import numpy as np
import time
shape = ( 20, 30, 40 )
ndata = int( 1e6 )
data = np.random.normal( loc = 10, scale = 5, size = ndata )
coords = np.vstack( [ np.random.uniform( 0, shape[i], ndata )
for i in range( len( shape ) ) ] ).T
max_data = np.zeros( shape )
start = time.time()
for i in range( len( data ) ) :
# shortcut to find bin indices when the bins are
# [ range( shape[i] ) for i in range( len( shape ) ) ]
bin_indices = tuple( coords[i].astype( int ) )
max_data[ bin_indices ] = max( max_data[ bin_indices ], data[ i ] )
elapsed = time.time() - start
print( 'elapsed: %.3e' % elapsed ) # 2.98 seconds on my computer