当前位置: 首页 > 面试题库 >

Pandas Dataframe:根据其地理坐标(经度和纬度)联接范围内的项目

秋飞鸾
2023-03-14
问题内容

我得到了一个数据框,其中包含经度和纬度的位置。想像一下城市。

df = pd.DataFrame([{'city':"Berlin", 'lat':52.5243700, 'lng':13.4105300},
                   {'city':"Potsdam", 'lat':52.3988600, 'lng':13.0656600},
                   {'city':"Hamburg", 'lat':53.5753200, 'lng':10.0153400}]);

现在,我正在尝试使所有城市都围绕另一个半径。假设距柏林500公里,距汉堡500公里的所有城市,等等。我将通过复制原始数据帧并将其与距离函数结合在一起来实现此目的。

中间结果如下所示:

Berlin --> Potsdam
Berlin --> Hamburg
Potsdam --> Berlin
Potsdam --> Hamburg
Hamburg --> Potsdam
Hamburg --> Berlin

分组(减少)后的最终结果应该是这样的。 备注: 如果值列表包含城市的所有列,那将很酷。

Berlin --> [Potsdam, Hamburg]
Potsdam --> [Berlin, Hamburg]
Hamburg --> [Berlin, Potsdam]

或者只是一个城市周围500公里内的城市数。

Berlin --> 2
Potsdam --> 2
Hamburg --> 2

由于我是Python的新手,所以请您从任何起点入手。我对Haversine距离很熟悉。但不确定Scipy或Pandas中是否有有用的距离/空间方法。

更新: 该问题的初衷来自两个Sigma Connect租赁列表Kaggle竞赛。想法是使那些列表在另一个列表周围100m。其中a)表示密度,因此是受欢迎的区域,b)如果地址是比较的,则可以找出是否有交叉路口并因此有嘈杂的区域。因此,由于您不仅需要比较距离,还需要比较地址和其他元数据,因此您不需要完整的项与项之间的关系。
PS: 我没有将解决方案上载到Kaggle。我只想学习。


问题答案:

您可以使用:

from math import radians, cos, sin, asin, sqrt

def haversine(lon1, lat1, lon2, lat2):

    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])

    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    r = 6371 # Radius of earth in kilometers. Use 3956 for miles
    return c * r

首先需要交叉与加入merge,删除一行,在相同的价值观city_x,并city_y通过boolean indexing

df['tmp'] = 1
df = pd.merge(df,df,on='tmp')
df = df[df.city_x != df.city_y]
print (df)
    city_x     lat_x     lng_x  tmp   city_y     lat_y     lng_y
1   Berlin  52.52437  13.41053    1  Potsdam  52.39886  13.06566
2   Berlin  52.52437  13.41053    1  Hamburg  53.57532  10.01534
3  Potsdam  52.39886  13.06566    1   Berlin  52.52437  13.41053
5  Potsdam  52.39886  13.06566    1  Hamburg  53.57532  10.01534
6  Hamburg  53.57532  10.01534    1   Berlin  52.52437  13.41053
7  Hamburg  53.57532  10.01534    1  Potsdam  52.39886  13.06566

然后应用Haversine函数:

df['dist'] = df.apply(lambda row: haversine(row['lng_x'], 
                                            row['lat_x'], 
                                            row['lng_y'], 
                                            row['lat_y']), axis=1)

滤镜距离:

df = df[df.dist < 500]
print (df)
    city_x     lat_x     lng_x  tmp   city_y     lat_y     lng_y        dist
1   Berlin  52.52437  13.41053    1  Potsdam  52.39886  13.06566   27.215704
2   Berlin  52.52437  13.41053    1  Hamburg  53.57532  10.01534  255.223782
3  Potsdam  52.39886  13.06566    1   Berlin  52.52437  13.41053   27.215704
5  Potsdam  52.39886  13.06566    1  Hamburg  53.57532  10.01534  242.464120
6  Hamburg  53.57532  10.01534    1   Berlin  52.52437  13.41053  255.223782
7  Hamburg  53.57532  10.01534    1  Potsdam  52.39886  13.06566  242.464120

而在去年创造list或获得sizegroupby

df1 = df.groupby('city_x')['city_y'].apply(list)
print (df1)
city_x
Berlin     [Potsdam, Hamburg]
Hamburg     [Berlin, Potsdam]
Potsdam     [Berlin, Hamburg]
Name: city_y, dtype: object

df2 = df.groupby('city_x')['city_y'].size()
print (df2)
city_x
Berlin     2
Hamburg    2
Potsdam    2
dtype: int64

也可以使用numpy haversine solution

def haversine_np(lon1, lat1, lon2, lat2):
    """
    Calculate the great circle distance between two points
    on the earth (specified in decimal degrees)

    All args must be of equal length.

    """
    lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2])

    dlon = lon2 - lon1
    dlat = lat2 - lat1

    a = np.sin(dlat/2.0)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2.0)**2

    c = 2 * np.arcsin(np.sqrt(a))
    km = 6367 * c
    return km

df['tmp'] = 1
df = pd.merge(df,df,on='tmp')
df = df[df.city_x != df.city_y]
#print (df)

df['dist'] = haversine_np(df['lng_x'],df['lat_x'],df['lng_y'],df['lat_y'])
    city_x     lat_x     lng_x  tmp   city_y     lat_y     lng_y        dist
1   Berlin  52.52437  13.41053    1  Potsdam  52.39886  13.06566   27.198616
2   Berlin  52.52437  13.41053    1  Hamburg  53.57532  10.01534  255.063541
3  Potsdam  52.39886  13.06566    1   Berlin  52.52437  13.41053   27.198616
5  Potsdam  52.39886  13.06566    1  Hamburg  53.57532  10.01534  242.311890
6  Hamburg  53.57532  10.01534    1   Berlin  52.52437  13.41053  255.063541
7  Hamburg  53.57532  10.01534    1  Potsdam  52.39886  13.06566  242.311890


 类似资料:
  • 我已经通过使用draw工具成功地创建了一个esri.Geometry.Geometry.Extent对象。在我的addToMap函数中(它是onDrawEnd事件的回调),我想要取出方框四角的纬度、经度。我拉出extend的xmin,xmax,ymin,ymax,我的wkid设置为几何对象的4326。基于我有限的理解,我假设x,y将在较长时间内,但考虑到x的值是5550,我不认为这是正确的。我做错

  • 我的表有两个浮动列,分别表示纬度和经度坐标。 我想使用PostGIS的ST_DWithin查找距离给定点一定距离内的所有记录。 的签名期望前两个参数是几何体或地理数据类型,因此我非常确定解决方案是将纬度/液化天然气坐标转换为地理坐标,但我无法让它工作。 以下是不起作用的: 我得到这个错误: 错误:函数st_geogfromtext(未知)不存在 第1行:从ST_DWithin(ST_GeogFro

  • 我有一张以色列地图。 我需要创建一个获得两个双参数(经度和纬度)的函数,该函数应该在地图图像中的那个区域上画一个小圆圈。 我有以下关于地图的信息: null 截图: https://gyazo.com/5a19dece37ebace496c6b8d68eb9ec3c

  • 我已经成功地创建了一个存储经度、纬度和类型点的模式。我已经用2dsphere为它编制了索引。我用的是mongodb和mongoose。 这是我的模式的代码片段

  • 问题内容: 我有一个按照以下示例结构的mysql表: 现在我想做的是创建一个查询,该查询将在搜索位置的选定公里内选择结果 因此,假设他们搜索“灰色河流”,然后选择“在20公里以内找到所有结果” 它显然应该选择“灰河”,但也应根据经度和纬度选择灰河20公里以内的所有位置。 我真的不知道该怎么做。我已经读过haversine公式,但不知道如何将其应用于mysql SELECT。 任何帮助将非常感激。

  • 问题内容: 我正在尝试将经纬度对转换为像素坐标。我发现了这种墨卡托投影,但我不理解代码。x_adj,y_adj变量是什么因素?当我在没有这些常量的情况下运行代码时,我的经/纬对就不在地图上,并且x和y像素坐标也不是我想要的。 问题答案: 这些变量从何而来 选择这些变量以使计算出的坐标与地图的背景图像匹配。如果知道地图的投影参数,则可以计算它们。但是我相信,它们很可能是通过反复试验而获得的。 如何计

  • 问题内容: 我具有纽约市纽约市的纬度/经度值;40.7560540,-73.9869510和地球的平面图像,即1000px×446px。 我希望能够使用Javascript将纬度/经度转换为X,Y坐标,该点将反映该位置。 因此,图像左上角的X,Y坐标将是;289、111 注意事项: 不用担心要使用哪种投影的问题,可以自己做假设,也可以按照自己知道的可行的方法进行操作 X,Y可以形成图像的任意一角

  • 问题内容: 我有一个类型为(com.vividsolutions.jts.geom.Geometry)的几何对象。它目前是经度,纬度形式,我想翻转坐标,使其经度为纬度,这样我就可以将其以GeoJSON格式用于mongodb。 我看到的约束是:a)我想翻转坐标的输入是Geometry对象。b)几何对象将是多边形类型或多多边形。c)我想在将类型强制转换为Polygon / multipolygon之前