【问题标题】:new column with coordinates using geopy pandas使用 geopy pandas 坐标的新列
【发布时间】:2015-10-03 13:17:41
【问题描述】:

我有一个 df:

import pandas as pd
import numpy as np
import datetime as DT
import hmac
from geopy.geocoders import Nominatim
from geopy.distance import vincenty

df


     city_name  state_name  county_name
0    WASHINGTON  DC  DIST OF COLUMBIA
1    WASHINGTON  DC  DIST OF COLUMBIA
2    WASHINGTON  DC  DIST OF COLUMBIA
3    WASHINGTON  DC  DIST OF COLUMBIA
4    WASHINGTON  DC  DIST OF COLUMBIA
5    WASHINGTON  DC  DIST OF COLUMBIA
6    WASHINGTON  DC  DIST OF COLUMBIA
7    WASHINGTON  DC  DIST OF COLUMBIA
8    WASHINGTON  DC  DIST OF COLUMBIA
9    WASHINGTON  DC  DIST OF COLUMBIA

我想获取下面数据框中任何一列的经纬度坐标。使用各个位置的文档时,文档 (http://geopy.readthedocs.org/en/latest/#data) 非常简单。

>>> from geopy.geocoders import Nominatim
>>> geolocator = Nominatim()
>>> location = geolocator.geocode("175 5th Avenue NYC")
>>> print(location.address)
Flatiron Building, 175, 5th Avenue, Flatiron, New York, NYC, New York,     ...
>>> print((location.latitude, location.longitude))
(40.7410861, -73.9896297241625)
>>> print(location.raw)
{'place_id': '9167009604', 'type': 'attraction', ...}

但是我想将该函数应用于 df 中的每一行并创建一个新列。我已经尝试了以下

df['city_coord'] = geolocator.geocode(lambda row: 'state_name' (row))

但我认为我的代码中缺少某些内容,因为我得到以下信息:

    city_name   state_name  county_name coordinates
0    WASHINGTON  DC  DIST OF COLUMBIA    None
1    WASHINGTON  DC  DIST OF COLUMBIA    None
2    WASHINGTON  DC  DIST OF COLUMBIA    None
3    WASHINGTON  DC  DIST OF COLUMBIA    None
4    WASHINGTON  DC  DIST OF COLUMBIA    None
5    WASHINGTON  DC  DIST OF COLUMBIA    None
6    WASHINGTON  DC  DIST OF COLUMBIA    None
7    WASHINGTON  DC  DIST OF COLUMBIA    None
8    WASHINGTON  DC  DIST OF COLUMBIA    None
9    WASHINGTON  DC  DIST OF COLUMBIA    None

我希望使用 Lambda 函数得到这样的结果:

     city_name  state_name  county_name  city_coord
0    WASHINGTON  DC  DIST OF COLUMBIA    38.8949549, -77.0366456 
1    WASHINGTON  DC  DIST OF COLUMBIA    38.8949549, -77.0366456 
2    WASHINGTON  DC  DIST OF COLUMBIA    38.8949549, -77.0366456 
3    WASHINGTON  DC  DIST OF COLUMBIA    38.8949549, -77.0366456 
4    WASHINGTON  DC  DIST OF COLUMBIA    38.8949549, -77.0366456 
5    WASHINGTON  DC  DIST OF COLUMBIA    38.8949549, -77.0366456 
6    WASHINGTON  DC  DIST OF COLUMBIA    38.8949549, -77.0366456 
7    WASHINGTON  DC  DIST OF COLUMBIA    38.8949549, -77.0366456 
8    WASHINGTON  DC  DIST OF COLUMBIA    38.8949549, -77.0366456 
9    WASHINGTON  DC  DIST OF COLUMBIA    38.8949549, -77.0366456
10   GLYNCO      GA  GLYNN               31.2224512, -81.5101023

感谢您的帮助。在我得到坐标后,我想绘制它们。任何用于映射坐标的推荐资源也非常感谢。谢谢

【问题讨论】:

    标签: python pandas geopy


    【解决方案1】:

    您可以调用apply 并传递您要在每一行上执行的函数,如下所示:

    In [9]:
    
    geolocator = Nominatim()
    df['city_coord'] = df['state_name'].apply(geolocator.geocode)
    df
    Out[9]:
        city_name state_name       county_name  \
    0  WASHINGTON         DC  DIST OF COLUMBIA   
    1  WASHINGTON         DC  DIST OF COLUMBIA   
    
                                              city_coord  
    0  (District of Columbia, United States of Americ...  
    1  (District of Columbia, United States of Americ...  
    

    然后您可以访问纬度和经度属性:

    In [16]:
    
    df['city_coord'] = df['city_coord'].apply(lambda x: (x.latitude, x.longitude))
    df
    Out[16]:
        city_name state_name       county_name                       city_coord
    0  WASHINGTON         DC  DIST OF COLUMBIA  (38.8937154, -76.9877934586326)
    1  WASHINGTON         DC  DIST OF COLUMBIA  (38.8937154, -76.9877934586326)
    

    或者通过两次调用apply 来一次性完成:

    In [17]:
    df['city_coord'] = df['state_name'].apply(geolocator.geocode).apply(lambda x: (x.latitude, x.longitude))
    df
    
    Out[17]:
        city_name state_name       county_name                       city_coord
    0  WASHINGTON         DC  DIST OF COLUMBIA  (38.8937154, -76.9877934586326)
    1  WASHINGTON         DC  DIST OF COLUMBIA  (38.8937154, -76.9877934586326)
    

    您的尝试 geolocator.geocode(lambda row: 'state_name' (row)) 也没有做任何事情,因此为什么您有一列充满 None

    编辑

    @leb 在这里提出了一个有趣的观点,如果您有许多重复值,那么对每个唯一值进行地理编码然后添加以下内容会更高效:

    In [38]:
    states = df['state_name'].unique()
    d = dict(zip(states, pd.Series(states).apply(geolocator.geocode).apply(lambda x: (x.latitude, x.longitude))))
    d
    
    Out[38]:
    {'DC': (38.8937154, -76.9877934586326)}
    
    In [40]:    
    df['city_coord'] = df['state_name'].map(d)
    df
    
    Out[40]:
        city_name state_name       county_name                       city_coord
    0  WASHINGTON         DC  DIST OF COLUMBIA  (38.8937154, -76.9877934586326)
    1  WASHINGTON         DC  DIST OF COLUMBIA  (38.8937154, -76.9877934586326)
    

    所以上面使用unique 获取所有唯一值,从它们构造一个字典,然后调用map 执行查找并添加坐标,这将比尝试按行进行地理编码更有效

    【讨论】:

    • 我仍然收到此错误:GeocoderTimedOut:服务超时。这是我正在做的事情吗?
    • 您的原始代码或优化版本是否出现此错误?如果地理编码超时,您可能必须分块处理数据
    【解决方案2】:

    支持并接受@EdChum 的回答,我只是想补充一下。他的方法效果很好,但从个人经验来看,我想分享几点:

    在处理地理编码时,如果您有多个重复的城市/州组合,则要快得多只发送 1 个进行地理编码,然后将其余部分复制到下面的其他行:

    非常对大数据很有帮助,可以通过两种方式完成:

    1. 仅基于您的数据,因为行似乎完全重复,并且仅当您需要时,删除额外的行并对其中之一执行地理编码。这可以使用drop_duplicate 来完成
    2. 如果您想保留所有行 group_by 城市/州组合,请通过调用 head(1) 对其第一个行应用地理编码,然后复制到其余行。

    原因是每次您调用 Nominatim 时都会出现一个小的延迟问题,即使您在同一城市/州连续排队也是如此。当您的数据变大时,这种小的延迟会变得更糟,从而导致巨大的响应延迟和可能的超时。

    再一次,这一切都来自个人处理它。如果现在对您没有好处,请记住以备将来使用。

    【讨论】:

    • 这是一个有趣的观点,最好只获取唯一值,对它们进行地理编码并将它们合并回来,我会更新我的答案
    • 感谢您的回复。非常有用的信息!虽然当我查看 [:5] 行数据时,我收到了一个很好的数据框。当我将该函数应用于所有(200,000 条记录)时,我收到了超时错误。我将不得不分组然后申请。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    相关资源
    最近更新 更多