Python模块用于存储和查询地理坐标

19

有没有一个Python模块可以创建带有地理位置坐标(纬度和经度)的对象,并查询所有距离给定坐标5公里范围内的对象?

我一直在尝试将纬度和经度存储为字典中的键(因为它们按键索引),并使用一些距离查找算法来查询它们。但是这感觉像是一种可怕的hack。

本质上,就像PostgreSQL的PostGIS一样,但全部在我的Python应用程序的内存中。

7个回答

20

是的,尝试使用 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.]

谢谢您的回答。我之前跳过了goepy,因为我认为它完全是用于地理编码的。通过查询示例,它不会循环遍历points中的每个对象吗?这并不像PostGIS对点进行索引那样高效 - 或许数据库方法会更有效。 - Jon Cox
@Jonathan - 你说得对,它会遍历整个点列表。我不知道geopy中是否有索引的可能性。也许你能找到一些信息。 - eumiro

6

我知道这不完全是你的意思,但你可以使用GeoDjango和一个内存中的SQLite数据库。它是一组完整的GIS工具,以Web应用程序形式呈现,使其成为快速开发GIS应用程序的瑞士军刀,特别适合小型临时查询。


2

在GIS中通常的方法是在兴趣点周围创建一个缓冲区并查询交集。正如@RyanDalton所建议的,如果您计划经常进行地理定位,那么请使用Shapely,这是Python的GIS API。即使您仍然需要空间索引(见下文),了解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

你的字典想法听起来还不错,但是你需要检查落在“相邻”字典键下的点。

如果你找不到合适的工具,并且喜欢编写算法,你可以实现一个二叉空间分区树,这是一种较少 hacky 的实现类似功能的方法。


1

您可以使用SQLite,它具有Rtree扩展程序,可用于进行此类存储和查询。如果您的数据大于要使用的内存或者您想在程序运行之间保存和操作数据,则此方法非常有用。实际的存储和查询代码是用C编写的,这意味着它必须被编译,但好处是比纯Python解决方案(如geopy)具有更高的性能。pysqlite或APSW都可以用于访问SQLite。(声明:我是APSW的作者。)


1

我有类似的问题,使用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)]

需要额外的工作才能获取半径范围内的所有点。
我尝试使用Shapely的STRtree,但性能更差(我使用pip install shapely[vectorized]安装了它)。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接