Home > Back-end >  Optimized coordinates selection in 2D numpy array
Optimized coordinates selection in 2D numpy array

Time:01-15

I have a numpy array of coordinates. I want to select those between Xmin and Xmax and between Ymin and Ymax.

Here is my code :

grid = np.random.randint(2, size=81).reshape(9,9)
List_of_coordinates = np.argwhere(grid == 0)
Xmin, Xmax, Ymin, Ymax = 0,3,6,9
List_of_coordinates = List_of_coordinates[List_of_coordinates[:, 1] >= Ymin]
List_of_coordinates = List_of_coordinates[List_of_coordinates[:, 1] < Ymax]
List_of_coordinates = List_of_coordinates[List_of_coordinates[:, 0] >= Xmin]
List_of_coordinates = List_of_coordinates[List_of_coordinates[:, 0] < Xmax]

Is there a faster way ?

CodePudding user response:

Slice first the grid, you'll get indices relative to the beginning of the slice, then add the start of the slice to come back to the absolute coordinates:

List_of_coordinates = (np.argwhere(grid[Xmin:Xmax,Ymin:Ymax] == 0)
                        np.array([Xmin,Ymin]))

Example

grid:

array([[0, 1, 0, 0, 0, 0, 0, 1, 1],
       [1, 0, 1, 0, 1, 0, 1, 0, 0],
       [0, 1, 0, 1, 0, 1, 0, 0, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1],
       [0, 1, 1, 1, 0, 0, 1, 0, 0],
       [1, 0, 0, 0, 0, 1, 1, 0, 0],
       [0, 0, 0, 0, 0, 1, 1, 0, 1],
       [1, 1, 0, 1, 1, 1, 1, 1, 0],
       [1, 0, 1, 0, 1, 0, 1, 0, 0]])

slice:

array([[0, 1, 1],
       [1, 0, 0],
       [0, 0, 1]])

coordinates of 0s:

array([[0, 6],
       [1, 7],
       [1, 8],
       [2, 6],
       [2, 7]])

CodePudding user response:

You can use argwhere again.

import numpy as np
grid = np.random.randint(2, size=81).reshape(9,9)
List_of_coordinates = np.argwhere(grid == 0)
Xmin, Xmax, Ymin, Ymax = 0,3,6,9
# select coordinates between Xmin and Xmax and Ymin and Ymax
coordinates = np.argwhere(
np.logical_and(List_of_coordinates[:,0] >= Xmin, List_of_coordinates[:,0] <= Xmax) &
np.logical_and(List_of_coordinates[:,1] >= Ymin, List_of_coordinates[:,1] <= Ymax)
)

CodePudding user response:

I (micro-)benchmarked your solution, an optimized version of your solution and @mozway's approach (I didn't include @Mohammad's answer, because the output is different, first results were about the same as the optimized original) with larger example data. Run on a 2-core google colab instance.

import numpy as np

grid = np.random.randint(2, size=(1000,1000))
Xmin, Xmax, Ymin, Ymax = 0,300,600,900
%%timeit
List_of_coordinates = np.argwhere(grid == 0)
List_of_coordinates = List_of_coordinates[List_of_coordinates[:, 1] >= Ymin]
List_of_coordinates = List_of_coordinates[List_of_coordinates[:, 1] < Ymax]
List_of_coordinates = List_of_coordinates[List_of_coordinates[:, 0] >= Xmin]
List_of_coordinates = List_of_coordinates[List_of_coordinates[:, 0] < Xmax]
List_of_coordinates

original solution 10 loops, best of 5: 30.1 ms per loop

%%timeit
List_of_coordinates = np.argwhere(grid == 0)
LoC = List_of_coordinates[
    (List_of_coordinates[:, 1] >= Ymin) &
    (List_of_coordinates[:, 1] < Ymax) &
    (List_of_coordinates[:, 0] >= Xmin) &
    (List_of_coordinates[:, 0] < Xmax)               
]
LoC

optimized original 100 loops, best of 5: 19.4 ms per loop

%%timeit
LoC = np.argwhere(grid[Xmin:Xmax, Ymin:Ymax] == 0)   np.array([Xmin,Ymin])
LoC

@mozway's solution 1000 loops, best of 5: 1.69 ms per loop

  •  Tags:  
  • Related