繁体   English   中英

如何在python中从Lat和Long获得带有关联邮政编码的Dataframe?

[英]How to get Dataframe with associated Zip codes from Lat and Long in python?

我正在尝试撤消地理编码并获取邮政编码。 我有一个表/数据框,它的经纬度为40万,我想通过解析经纬度来获取邮政编码。

以下是样本数据框

data = {'Site 1': '31.336968, -109.560959',
        'Site 2': '31.347745, -108.229963',
        'Site 3': '32.277621, -107.734724',
        'Site 4': '31.655494, -106.420484',
        'Site 5': '30.295053, -104.014528'}

我的代码:

import geopandas as gpd
from shapely.geometry import Point
gdf_locations = gpd.read_file('/Users/admin/Downloads/tl_2016_us_zcta510/tl_2016_us_zcta510.shp')

我从这里下载了tl_2016_us_zcta510.shp文件

这就是我被困住的地方。 我尝试的一种解决方案是将其转换为NUMPY数组并传递值。 但这似乎非常缓慢。 我想将其作为使用lambda的数据框并快速获得结果。

我试过的

               [Longitude]    [Latitude]
x = np.array((-73.986946106, 40.284328461))
x_pnt = Point(x)
filter = gdf_locations['geometry'].contains(x_pnt)
print(gdf_locations.loc[filter, 'GEOID10'])

虽然这给了我想要的东西,但是它非常慢。 如何使它更快并作为递归函数? 任何帮助表示赞赏。 谢谢。

PS:我已经看过许多博客文章和有关该主题的文章,但是似乎没有人针对大规模的实时实现解决它。

编辑:我特别希望获得具有以下结构的数据框:

 data = {'Site 1': '31.336968, -109.560959', 94108,
            'Site 2': '31.347745, -108.229963', 60616,
            'Site 3': '32.277621, -107.734724', 78654,
            'Site 4': '31.655494, -106.420484', 78090,
            'Site 5': '30.295053, -104.014528', 78901}

我了解如何将经纬度长期转换为Zip,但我无法做到的是获取数据帧。 希望这使事情更加清楚。

我还没有使用过Geopandas,但是我会尝试使用scipy的cKDTree 对于您拥有的数据量,它应该非常快。 唯一的事情是它适用于点对点查找,因此您必须使用邮政编码数据集中的多边形的质心。

例如,将质心点的质心转换为numpy数组:

centroids = gdf_locations.centroid

# transform shapely points to np array
point_array = []
for centroid in centroids:
    point_array.append([centroid.x, centroid.y])
point_array = np.array(point_array)
print(point_array[0])
>>> array([-83.61511443,  41.31279856])

为确保快速查找,我创建了400,000个随机坐标:

random_lat_long = np.random.randn(400000, 2) * 80
print(random_lat_long)
>>> array([ -8.37429385, -23.19458311])

现在为最接近的点:

distance, index = spatial.cKDTree(point_array).query(random_lat_long)

在我的计算机中,使用Jupyter中的%%timeit ,这大约花费了1.7秒。

最后,从数据框中获取邮政编码:

zip_codes = gdf_locations.loc[index, 'GEOID10']

编辑:将纬度和经度作为结果的一部分:

提取数据并转换类型:

lats_lons_zips = gdf_locations.loc[index, ['INTPTLAT10', 'INTPTLON10', 'GEOID10']]
# keep the zip code as an str to preserve leading zeros
lats_lons_zips = lats_lons_zips.astype({"INTPTLAT10": float, "INTPTLON10": float, "GEOID10": str})

将索引更改为“站点XX”:

new_index = ["Site " + str(i) for i in range(len(lats_lons_zips))]
lats_lons_zips.index = new_index

最后,得到结果:

print(lats_lons_zips.iloc[0:4].to_dict(orient="index"))
{ 'Site 0': { 'GEOID10': '00824',
              'INTPTLAT10': 17.7445568,
              'INTPTLON10': -64.6829328},
  'Site 1': { 'GEOID10': '96916',
              'INTPTLAT10': 13.2603723,
              'INTPTLON10': 144.7006789},
  'Site 2': { 'GEOID10': '96916',
              'INTPTLAT10': 13.2603723,
              'INTPTLON10': 144.7006789},
  'Site 3': { 'GEOID10': '04741',
              'INTPTLAT10': 47.453712,
              'INTPTLON10': -69.2229208}}

也许您需要geopandas.sjoin

在空间连接中,两个几何对象基于它们之间的空间关系进行合并。

首先,您需要将站点数据准备为geoDataFrame。

import geopandas as gpd
import pandas as pd
from shapely.geometry import Point

gdf_locations = gpd.read_file('tempdata/tl_2016_us_zcta510.shp')
data = {'Site 1': '31.336968, -109.560959',
        'Site 2': '31.347745, -108.229963',
        'Site 3': '32.277621, -107.734724',
        'Site 4': '31.655494, -106.420484',
        'Site 5': '30.295053, -104.014528'}
df_site = pd.DataFrame.from_dict(data, orient='index',columns=['locstr'])
df_site['loc'] = df_site['locstr'].apply(lambda x: list(map(float,x.split(','))))
df_site['loc'] = df_site['loc'].apply(lambda x: Point(x[1],x[0]))
gdf_site = gpd.GeoDataFrame(df_site,geometry=df_site['loc'],crs=gdf_locations.crs).drop(['loc'], axis=1)
print(gdf_site)

                        locstr                       geometry
Site 1  31.336968, -109.560959  POINT (-109.560959 31.336968)
Site 2  31.347745, -108.229963  POINT (-108.229963 31.347745)
Site 3  32.277621, -107.734724  POINT (-107.734724 32.277621)
Site 4  31.655494, -106.420484  POINT (-106.420484 31.655494)
Site 5  30.295053, -104.014528  POINT (-104.014528 30.295053)

然后,您可以设置op='intersects'来判断站点和shp之间的空间关系。

相交:如果对象的边界和内部以任何方式与另一个对象的边界和/或内部相交,则属性将被合并。

gdf_site = gpd.sjoin(gdf_site,gdf_locations,how='left',op='within')
print(gdf_site[['locstr','GEOID10']])

                        locstr GEOID10
Site 1  31.336968, -109.560959   85607
Site 2  31.347745, -108.229963   88040
Site 3  32.277621, -107.734724   88030
Site 4  31.655494, -106.420484     NaN
Site 5  30.295053, -104.014528   79843

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM