Python модуль для хранения и запроса географических координат - PullRequest
17 голосов
/ 31 января 2012

Существует ли модуль Python, в котором я могу создавать объекты с географической координатой местоположения (широтой и долготой) и запрашивать все объекты на предмет тех, которые находятся на расстоянии 5 км (то есть в радиусе) от заданной координаты?

Я пытался сохранить широту и долготу в качестве ключей в словарях (так как они проиндексированы по ключам) и использовать некоторые алгоритмы определения расстояния для их запроса.Но это похоже на ужасный взлом.

По сути, что-то вроде PostGIS for PostgreSQL, но все в памяти моего приложения Python.

Ответы [ 7 ]

17 голосов
/ 31 января 2012

Да, попробуйте geopy .

import geopy
import geopy.distance

pt1 = geopy.Point(48.853, 2.349)
pt2 = geopy.Point(52.516, 13.378)

dist = geopy.distance.distance(pt1, pt2).km
# 878.25

, после чего вы можете запросить свои списки точек:

[pt for pt in points if geopy.distance.distance(orig, pt).km < 5.]
5 голосов
/ 31 января 2012

Я знаю, что это не совсем то, что вы имели в виду, но вы можете использовать GeoDjango с базой данных SQLite в памяти.Это полный набор ГИС-инструментов, представленных в виде веб-приложения, что делает его швейцарским армейским ножом для быстрой разработки ГИС-приложений, особенно для небольших специальных запросов.

2 голосов
/ 01 февраля 2012

Обычный подход в ГИС - создать буфер вокруг точки интереса и запросить пересечение. Как говорит @RyanDalton, если вы планируете делать много геолокации, используйте Shapely, GIS API для Python. Полезно знать о Shapely, даже если вам все еще нужен пространственный индекс (см. Ниже). Вот как создать буферы в Shapely:

distance = 3
center = Point(1, 1)
pts = [Point(1.1, 1.2),Point(1.2,1.2)]
center_buf = a.buffer(distance)
#filters the points list according to whether they are contained in the list
contained = filter(center_buf.contains,pts)

Вы можете индексировать свои баллы самостоятельно (скажем, по долготе, например), если у вас их немного. В противном случае вы также можете использовать пакет Rtree, проверьте ссылку под названием Использование Rtree в качестве дешевой пространственной базы данных !

1 голос
/ 02 февраля 2012

Вы можете использовать SQLite с расширением Rtree для выполнения именно такого рода хранилища и запросов. Этот подход полезен, если ваши данные больше памяти, которую вы хотите использовать, или вы хотите сохранять и манипулировать данными между запусками программы. Фактический код хранения и запроса находится на C, что означает, что он должен быть скомпилирован, но преимущество заключается в дополнительной производительности по сравнению с чистыми решениями Python, такими как geopy. Для доступа к SQLite будет работать pysqlite или APSW. (Раскрытие: я автор APSW.)

1 голос
/ 31 января 2012

Ваша идея словаря звучит не так уж и плохо, хотя вам нужно будет проверить точки, которые также попадают под «соседние» ключи словаря.

Если вы не можете найти правильный инструмент и, например, алгоритмы кодирования, вы можете реализовать дерево разделов двоичного пространства, которое afaik является менее хакерским способом достижения подобной вещи.

0 голосов
/ 04 марта 2019

У меня похожая проблема, и кажется, что использование SciPy cKDTree для быстрого поиска ближайших точек вместе с GeoPy для расчета географического расстояния работает нормально.

In [1]: import numpy as np
In [2]: from scipy.spatial import cKDTree
In [3]: from geopy import Point, distance
In [4]: points = np.random.sample((100000, 2)) * 180 - 90   # make 100k random lat-long points
In [5]: index = cKDTree(points)
In [6]: %time lat_long_dist, inds = index.query(points[234], 20)
CPU times: user 118 µs, sys: 164 µs, total: 282 µs
Wall time: 248 µs
In [7]: points_geopy = [Point(*p) for p in points]
In [8]: %time geo_dists = [distance.great_circle(points_geopy[234], points_geopy[i]) for i in inds]
CPU times: user 244 µs, sys: 218 µs, total: 462 µs
Wall time: 468 µs
In [9]: geo_dists
Out[9]: 
[Distance(0.0),
 Distance(29.661520907955524),
 ...
 Distance(156.5471729956897),
 Distance(144.7528417712309)]

Немного дополнительной работы необходимо, чтобы получить все точки в радиусе.

Я попробовал STRtree Shapely, но получил намного худшую производительность (я установил с pip install shapely[vectorized]).

0 голосов
/ 01 февраля 2012

Вы смотрели на Shapely ? У него есть несколько методов для запроса объектов на расстоянии. Взгляните на двоичные пространственные предикаты . Это может быть просто то, что вы ищете.

...