使用python查找土地中最近的位置坐标

使用python查找土地中最近的位置坐标,python,geocode,Python,Geocode,地理编码api不返回海洋/海洋坐标的位置信息。对于这些记录,我希望找到具有有效位置信息的可能最近的坐标(即最近的陆地坐标) 下面是通过传递坐标获取位置信息的代码 import requests request_url = "https://api.mapbox.com/geocoding/v5/mapbox.places/{0}%2C{1}.json?access_token={2}&types=country&limit=1".format(lng,lat,key) r

地理编码api不返回海洋/海洋坐标的位置信息。对于这些记录,我希望找到具有有效位置信息的可能最近的坐标(即最近的陆地坐标) 下面是通过传递坐标获取位置信息的代码

import requests    
request_url = "https://api.mapbox.com/geocoding/v5/mapbox.places/{0}%2C{1}.json?access_token={2}&types=country&limit=1".format(lng,lat,key)
response = requests.get(request_url)
output = response.json()
我找不到最近的地点。我也是Python新手

样本输出:

{'type': 'FeatureCollection',
 'query': [32.12, 54.21],
 'features': [{'id': 'country.10008046970720960',
   'type': 'Feature',
   'place_type': ['country'],
   'relevance': 1,
   'properties': {'short_code': 'ru', 'wikidata': 'Q159'},
   'text': 'Russia',
   'place_name': 'Russia',
   'bbox': [19.608673, 41.185353, 179.9, 81.961618],
   'center': [37.61667, 55.75],
   'geometry': {'type': 'Point', 'coordinates': [37.61667, 55.75]}}],
 'attribution': 'NOTICE: © 2020 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained. POI(s) provided by Foursquare.'}
坐标为海洋时的输出:

{'type': 'FeatureCollection',
 'query': [0, 0],
 'features': [],
 'attribution': 'NOTICE: © 2020 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained. POI(s) provided by Foursquare.'}
用于根据纬度和经度查找最近的点(如城市)。
def dist_在两个平面之间(*args):
从数学输入asin,cos,弧度,sin,sqrt
lat1,lat2,long1,long2=贴图(弧度,args)
dist_lats=abs(lat2-lat1)
dist_longs=abs(long2-long1)
a=正弦波(距离-纬度/2)**2+正弦波(纬度1)*正弦波(纬度2)*正弦波(距离-纬度/2)**2
c=asin(sqrt(a))*2
半径_earth=6378#“地球半径”R在两极为6356.752 km,在赤道为6378.137 km。
返回c*半径_接地
def查找最近的纬度(数据,v):
尝试:
return min(数据,key=lambda p:two-lat-lon(v['lat'],p['lat'],v['lon'],p['lon'])之间的距离)
除类型错误外:
打印('不是列表或不是数字')
#城市={'lat_key':值,'lon_key':值}类型:dict()
纽约={'lat':40.712776,'lon':-74.005974}
华盛顿={'lat':47.751076,'lon':-120.740135}
旧金山={'lat':37.774929,'lon':-122.419418}
城市列表=[纽约、华盛顿、旧金山]
城市:29.760427,伦敦:95.369804,休斯顿
打印(查找最近的(城市列表,城市到查找))
这将产生:

{'lat':47.751076,'lon':-120.740135}对应于华盛顿
假设您从mapbox获得了四个json答案,并将它们保存在一个列表中:
json_answers=list()#=[]
json_answers.append({'type':'FeatureCollection',
“查询”:[32.12,54.21],
'features':[{'id':'country.10008046970720960',
“类型”:“特征”,
“地点类型”:[“国家],
"相关性":1,,
'属性':{'short_code':'ru','wikidata':'Q159'},
"文本":"俄罗斯",,
“地名”:“俄罗斯”,
"bbox":[19.608673,41.185353,179.9,81.961618],,
“中心”:[37.61667,55.75],
'几何体':{'类型':'点','坐标':[37.61667,55.75]},
“归属”:“通知:…”})
#对于这个例子,我只更改了“坐标”值
json_answers.append({'type':'FeatureCollection',
“查询”:[32.12,54.21],
'features':[{'id':'country.10008046970720960',
“类型”:“特征”,
“地点类型”:[“国家],
"相关性":1,,
'属性':{'short_code':'ru','wikidata':'Q159'},
"文本":"俄罗斯",,
“地名”:“俄罗斯”,
"bbox":[19.608673,41.185353,179.9,81.961618],,
“中心”:[37.61667,55.75],
“几何体”:{“类型”:“点”,“坐标”:[38.21667,56.15]}},
“归属”:“通知:…”})
#对于这个例子,我只更改了“坐标”值
json_answers.append({'type':'FeatureCollection',
“查询”:[32.12,54.21],
'features':[{'id':'country.10008046970720960',
“类型”:“特征”,
“地点类型”:[“国家],
"相关性":1,,
'属性':{'short_code':'ru','wikidata':'Q159'},
"文本":"俄罗斯",,
“地名”:“俄罗斯”,
"bbox":[19.608673,41.185353,179.9,81.961618],,
“中心”:[37.61667,55.75],
'几何体':{'类型':'点','坐标':[33.21667,51.15]},
“归属”:“通知:…”})
#最后一个答案是“空”
json_answers.append({'type':'FeatureCollection',
“查询”:[0,0],
“功能”:[],
“归属”:“通知:…”})
合作列表=[]
对于json_答案中的答案:
如果回答['features']:#检查['features']是否为空
#我不确定是[lat,lon]还是[lon,lat](您可以在mapbox上验证)
打印(f“坐标在[lat,lon]:{回答['features'][0]['geometry']['Coordinates']}”)
lat=回答['features'][0]['geometry']['coordinates'][0]
lon=回答['features'][0]['geometry']['coordinates'][1]
temp_dict={'lat':lat'lon':lon}
合作列表追加(临时目录)
打印(f“坐标列表={坐标列表}”)
指向查找={'lat':37.41667,'lon':55.05}休斯顿
打印(f“点到点查找={点到点查找}”)
打印(f“查找最近的位置={查找最近的位置(坐标列表,指向查找)}”)
这将产生:

{'lat':47.751076,'lon':-120.740135}
[lat,lon]中的坐标:[37.61667,55.75]
[lat,lon]中的坐标:[38.21667,56.15]
[lat,lon]中的坐标:[33.21667,51.15]
坐标列表=[{'lat':37.61667,'lon':55.75},{'lat':38.21667,'lon':56.15},{'lat':33.21667,'lon':51.15}]
指向查找={'lat':37.41667,'lon':55.05}
查找最接近的长度={'lat':38.21667,'lon':56.15}

使用python中的
反向地理编码
库获取最近的城市和国家

例如:

import reverse_geocode

coordinates = (-37.81, 144.96), (31.76, 35.21)

reverse_geocode.search(coordinates)
结果:

[{'city':'Melbourne','code':'AU','country':'Australia'}, {‘城市’:‘耶路撒冷’,‘代码’:‘伊尔’,‘国家’:‘以色列’}]


这是一个未优化的解决方案

在功能的引擎盖下发生了什么:

  • 在点上运行
    GeoPy
    反向查找
  • 如果找到该点,请返回其国家/地区名称
  • 如果找不到该点,请在
    world\u geometry
    变量中搜索最近的陆地点
  • 在最近的点上执行反向查找
  • 返回该点的国家名称(如果存在)或地区名称(如果没有国家名称)

  • 结果的精度取决于您提供的land几何图形的精度。例如,
    geopandas
    的世界几何图形非常好。我能找到所有国家的名字,除了巴哈马群岛中一些最小的岛屿。那些它找不到的被函数标记为“百慕大三角”,这对我来说已经足够好了。

    你能分享一下
    输出的样子吗?谢谢拉斐尔,这看起来不错。我想我们需要列出所有主要城市及其坐标。但在我们的业务中,它可以是一个小镇,也可以是一个城市
    
    from geopy.geocoders import Nominatim
    from shapely.ops import nearest_points
    
    def country_lookup(query, geocoder, land_geometry):
        
        try:
            loc = geocoder.reverse((query.y, query.x))
            return loc.raw['address']['country']
        except (KeyError, AttributeError):
            _, p2 = nearest_points(query, land_geometry)
            loc = geocoder.reverse((p2.y, p2.x)).raw['address']
            if 'country' in loc.keys():
                return loc['country']
            else:
                return loc['locality']
            
    # get world (or any land) geometry, instantiate geolocator service
    world = gp.read_file(gp.datasets.get_path('naturalearth_lowres'))
    world_geometry = world.geometry.unary_union
    geolocator = Nominatim(user_agent="GIW")
    
    # Create a column of country names from points in a GDF's geometry.
    gdf['country'] = gdf.geometry.apply(country_lookup, args=(geolocator, world_geometry))