【发布时间】:2016-03-14 02:00:39
【问题描述】:
我有一个包含两列(纬度、经度)的 csv 文件,其中包含超过 500 万行的地理位置数据。
我需要识别不在列表中任何其他点 5 英里范围内的点,并将所有内容输出回另一个具有额外列 (CloseToAnotherPoint) 的 CSV,如果有另一个点在 5 以内,则为 True英里,如果没有,False。
这是我目前使用geopy的解决方案(不进行任何网络调用,仅使用该函数计算距离):
from geopy.point import Point
from geopy.distance import vincenty
import csv
class CustomGeoPoint(object):
def __init__(self, latitude, longitude):
self.location = Point(latitude, longitude)
self.close_to_another_point = False
try:
output = open('output.csv','w')
writer = csv.writer(output, delimiter = ',', quoting=csv.QUOTE_ALL)
writer.writerow(['Latitude', 'Longitude', 'CloseToAnotherPoint'])
# 5 miles
close_limit = 5
geo_points = []
with open('geo_input.csv', newline='') as geo_csv:
reader = csv.reader(geo_csv)
next(reader, None) # skip the headers
for row in reader:
geo_points.append(CustomGeoPoint(row[0], row[1]))
# for every point, look at every point until one is found within 5 miles
for geo_point in geo_points:
for geo_point2 in geo_points:
dist = vincenty(geo_point.location, geo_point2.location).miles
if 0 < dist <= close_limit: # (0,close_limit]
geo_point.close_to_another_point = True
break
writer.writerow([geo_point.location.latitude, geo_point.location.longitude,
geo_point.close_to_another_point])
finally:
output.close()
您可能会看到它,这个解决方案非常慢。实际上太慢了,以至于我让它运行了 3 天,但它仍然没有完成!
我曾考虑过尝试将数据拆分为多个块(多个 CSV 文件或其他内容),这样内部循环就不必查看所有其他点,但是我必须弄清楚如何制作确保每个部分的边界都与其相邻部分的边界进行了检查,这似乎过于复杂,恐怕这比它的价值更令人头疼。
那么有什么方法可以加快速度吗?
【问题讨论】:
-
我不是地理专家,但我最初的直觉反应是通过消除目标周围 5x5 平方英里之外的点来对数据进行分类。这应该可以通过计算 5 英里是多少弧秒并简单地比较数字来实现....
-
你能给我们一个样本数据集吗?
-
这里的低调是如何使这不是 O(n) + O(n^2) 操作...我还应该指出,这种事情是旅行推销员问题。