6

好吧,我半途而废了。我正在使用 geopy 对数据框进行地理编码。我编写了一个简单的函数来接受输入 - 国家名称 - 并返回纬度和经度。我使用 apply 来运行该函数,它返回一个 Pandas 系列对象。我似乎无法将其转换为数据框。我确定我遗漏了一些明显的东西,但我是 python 新手,仍然是 RTFMing。顺便说一句,地理编码器功能很好用。

# Import libraries 
import os 
import pandas as pd 
import numpy as np
from geopy.geocoders import Nominatim

def locate(x):
    geolocator = Nominatim()
    # print(x) # debug
    try:
        #Get geocode
        location = geolocator.geocode(x, timeout=8, exactly_one=True)
        lat = location.latitude
        lon = location.longitude
    except:
        #didn't work for some reason that I really don't care about
        lat = np.nan
        lon = np.nan
   #  print(lat,lon) #debug
    return lat,  lon # Note: also tried return { 'LAT': lat, 'LON': lon }

df_geo_in = df_addr.drop_duplicates(['COUNTRY']).reset_index()    #works perfectly
df_geo_in['LAT'], df_geo_in['LON']  = df_geo_in.applymap(locate) 
# error: returns more than 2 values - default index + column with results

我也试过

df_geo_in['LAT','LON'] = df_geo_in.applymap(locate)

我得到一个没有索引的数据框和一个包含系列的列。

我尝试了许多其他方法,包括 'applymap' :

source_cols = ['LAT','LON'] 
new_cols = [str(x) for x in source_cols]

df_geo_in = df_addr.drop_duplicates(['COUNTRY']).set_index(['COUNTRY']) 
df_geo_in[new_cols] = df_geo_in.applymap(locate)

很长一段时间后返回错误:

ValueError:列的长度必须与键的长度相同

我还尝试使用该df.from_dict(df_geo_in)方法手动将系列转换为数据框,但没有成功。

目标是对 166 个独特的国家/地区进行地理编码,然后将其连接回 df_addr 中的 188K 地址。我试图在我的代码中成为 pandas-y 并且尽可能不编写循环。但我还没有找到将系列转换为数据帧的魔力,这是我第一次尝试使用 apply。

在此先感谢 - 古代 C 程序员

4

2 回答 2

7

我假设这df_geo是一个带有单列的df,所以我相信以下应该有效:

改变:

return lat,  lon

return pd.Series([lat,  lon])

那么你应该能够像这样分配:

df_geo_in[['LAT', 'LON']] = df_geo_in.apply(locate)

您尝试做的是将结果分配applymap给 2 个新列,这在此处是不正确的,因为applymap它旨在处理 df 中的每个元素,因此除非 lhs 具有相同的预期形状,否则不会给出所需的结果。

您的后一种方法也不正确,因为您删除了重复的国家,然后期望这会重新分配每个国家/地区的地理位置,但形状不同。

大型df创建地理定位非重复df然后将其合并回更大的df可能会更快,如下所示:

geo_lookup = df_addr.drop_duplicates(['COUNTRY'])
geo_lookup[['LAT','LNG']] = geo_lookup['COUNTRY'].apply(locate)
df_geo_in.merge(geo_lookup, left_on='COUNTRY', right_on='COUNTRY', how='left')

这将创建一个具有地理位置地址的非重复国家/地区的 df,然后我们执行左合并回到主 df。

于 2015-03-31T07:38:33.873 回答
0

使用一些示例数据总是更容易测试,但请尝试以下 zip 函数,看看它是否有效。

df_geo_in['LAT_LON'] = df_geo_in.applymap(locate) 
df_geo_in['LAT'], df_geo_in['LON'] = zip(*df_geo_in.LAT_LON)
于 2015-03-31T03:20:27.053 回答