【问题标题】:Efficient way to calculate geographic density in Pandas?计算熊猫地理密度的有效方法?
【发布时间】:2017-09-21 08:54:47
【问题描述】:

我有大量与美国快餐店相对应的经度和纬度数据。对于每个快餐店,我想知道 5 英里范围内还有多少其他快餐店。我可以像这样使用 Geopy 在 Pandas 中计算这个(DataFrame 中的每一行都是不同的快餐店):

import pandas as pd
import geopy.distance

df = pd.DataFrame({'Fast Food Place':[1,2,3], 'Lat':[33,34,35], 'Lon':[42,43,44]})

for index1, row1 in df.iterrows():
    num_fastfood = 0

    for index2, row2 in df.iterrows():
        # calculate distance in miles between longitude and latitude
        dist = geopy.distance.VincentyDistance(row1[['Lat','Lon']],
                                               row2[['Lat','Lon']]).miles

        # if fast food is within 5 miles, increment num_fastfood
        if dist < 5: # if less than five miles
            num_fastfood = num_fastfood + 1

    df.loc[index1, 'num_fastfood_5miles'] = num_fastfood - 1 # (subtract 1 to exclude self)

但这在非常大的数据集(即 50,000 行)上非常慢。我考虑使用 KDTree 进行搜索,但想知道其他人是否有更快的方法?

【问题讨论】:

  • KDTrees 在这项任务中很难被击败。有什么特殊原因使用一个吗?
  • @Paul 不是特别 - 更多的好奇心。我很快就会记住如何使用 sklearn 的 KDTree 设置。像tree = KDTree(my_lat_long) # Query all the values nnDist, nnIdx = tree.query(my_lat_long) 这样的东西然后循环通过nnDist?
  • 不,使用query_ball_tree 获取半径内的所有点:tree = KDTree(my_lat_long); within_5 = tree.query_ball_tree(tree, radius=5)。然后将嵌套列表展平并计数。
  • @Paul 没有意识到它的存在,谢谢。如果我这样做,它只会查看经纬度,但我需要合并 geopy 以获得以英里为单位的“真实”距离
  • 只需预先计算 5 英里的度数,然后使用纬度/经度。

标签: python performance loops pandas geolocation


【解决方案1】:

scipy.spatial.cKDTree实现:

from scipy.spatial import cKDTree

def find_neighbours_within_radius(xy, radius):
    tree = cKDTree(xy)
    within_radius = tree.query_ball_tree(tree, r=radius)
    return within_radius

def flatten_nested_list(nested_list):
    return [item for sublist in nested_list for item in sublist]

def total_neighbours_within_radius(xy, radius):
    neighbours = find_neighbours_within_radius(xy, radius)
    return len(flatten_nested_list(neighbours))

【讨论】:

  • 我收到了这个更新的错误TypeError: query_ball_tree() takes at least 2 positional arguments (1 given):没关系,我知道我必须分别提供纬度/经度距离
  • 抱歉,关键字是r,不是cKDTree.query_ball_tree 的半径。修复了代码。
猜你喜欢
  • 2020-12-04
  • 1970-01-01
  • 2020-07-24
  • 2016-09-18
  • 2013-05-12
  • 1970-01-01
  • 2013-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多