For a list of (x, y) points, I am trying to find the nearby points for each point.
from collections import defaultdict
from math import sqrt
from random import randint
# Generate a list of random (x, y) points
points = [(randint(0, 100), randint(0, 100)) for _ in range(1000)]
def is_nearby(point_a, point_b, max_distance=5):
"""Two points are nearby if their Euclidean distance is less than max_distance"""
distance = sqrt((point_b[0] - point_a[0])**2 + (point_b[1] - point_a[1])**2)
return distance < max_distance
# For each point, find nearby points that are within a radius of 5
nearby_points = defaultdict(list)
for point in points:
for neighbour in points:
if point != neighbour:
if is_nearby(point, neighbour):
nearby_points[point].append(neighbour)
Is there any way I can index points
to make the above search faster? I feel there must be some faster way than O(len(points)**2).
Edit: the points in general could be floats, not just ints
this is a version with a fixed grid where each gridpoint holds the number of samples that are there.
the search can then be reduced to just the space around the point in question.
for further optimzation: the tests for
x
andy
could be precalculated for a given gridsize - themath.hypot(point[0]-x, point[1]-y)
would not have to be done then for every point.and it may be a good idea to replace the grid with a
numpy
array.UPDATE
if your points are
float
s you can still create anint
grid to reduce the search space:the output looks something like this:
for convenience
Points
is now a class. may not be necessary though...depending on how dense or sparse your points are you could also represent the grid as a dictionary pointing to a list or
Points
...also the
find_neighbours
function accepts a startingpoint
consisting ofint
s only in that version. this might also be refined.and there is much room for improvement: the range of the
y
axis can be restricted using trigonometry. and for the points way inside the circle there is no need for an individual check; detailed checking only needs to be done close to the outer rim of the circle.