Reputation: 361
In a time series data, I have (x,y) coordinates for an object that evolve over a 2-D grid. For example:
(41.797, 34.0),
(42.152, 34.56),
(42.383, 36.07),
(42.505, 37.97)
How do I index the array in a way that array[x,y]=object_id. Subsequently, I'd need to go through this time-indexed 2-D grid again, and index array[x',y']=object_id_2. Where x' and y' are like a list above.
Upvotes: 2
Views: 3384
Reputation: 1296
It is possible to index a numpy array using floating point indices, you just need to interpolate between values. Here is code that will do that, using bilinear interpolation (taken from this gist)
def subsample_image(coords, img):
"""
Given a list of floating point coordinates (Nx2) in the image,
return the pixel value at each location using bilinear interpolation.
"""
if len(img.shape) == 2:
img = np.expand_dims(img, 2)
xs, ys = coords[:, 0], coords[:, 1]
pxs = np.floor(xs).astype(int)
pys = np.floor(ys).astype(int)
dxs = xs-pxs
dys = ys-pys
wxs, wys = 1.0-dxs, 1.0-dys
weights = np.multiply(img[pys, pxs, :].T , wxs*wys).T
weights += np.multiply(img[pys, pxs+1, :].T , dxs*wys).T
weights += np.multiply(img[pys+1, pxs, :].T , wxs*dys).T
weights += np.multiply(img[pys+1, pxs+1, :].T , dxs*dys).T
return weights
Upvotes: 2
Reputation: 1051
There are a few problems here.
First, you can't index by floats because it doesn't make any sense. Second, if you could, there is a problem with the way floats are interpreted/calculated (the reason why sometimes your results are like 3.99999999 instead of 4).
My recommendation is to index your values using a dictionary rounded to a certain number of decimals. This way you will ensure your data always matches!
Since you cannot map stuff by immutable keys, you need a tuple.
An example of how this would work:
mydict = {}
a = (41.797, 34.0)
object_a = 'A'
b = (42.152, 34.56)
object_b 'B'
mydict[round(a[0], 3), round(a[1], 3)] = object_a
mydict[round(b[0], 3), round(b[1], 3)] = object_b
print ( my_dict[round(a[0], 3), round(a[1], 3)] )
print ( my_dict[round(b[0], 3), round(b[1], 3)] )
>> 'A'
>> 'B'
If you want to update the object you simply use the rounded tuple
mydict[round(a[0], 3), round(a[1], 3)] = 'CHICKEN'
print ( my_dict[round(a[0], 3), round(a[1], 3)] )
print ( my_dict[round(b[0], 3), round(b[1], 3)] )
>> 'CHICKEN'
>> 'B'
If the code gets too messy, just add a function to round tuples:
def round_tuple(tupl, decimals=3):
return round(tupl[0], decimals), round(tupl[1], decimals)
This way you just do this:
target = round_tuple(tup)
mydict[target] = 'CHICKEN'
Upvotes: 1