Har*_*vey 6 python apply geopy geocode pandas
好吧,我半个智慧结束了.我用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
Run Code Online (Sandbox Code Playgroud)
我也试过了
df_geo_in['LAT','LON'] = df_geo_in.applymap(locate)
Run Code Online (Sandbox Code Playgroud)
我得到一个没有索引的单个数据帧和一个包含该系列的单个colume.
我尝试过其他一些方法,包括'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)
Run Code Online (Sandbox Code Playgroud)
很长一段时间后返回错误:
ValueError:列的长度必须与key相同
我也尝试使用该df.from_dict(df_geo_in)方法手动将系列转换为数据帧,但没有成功.
目标是对166个唯一国家进行地理编码,然后将其加入df_addr中的188K地址.我试图在我的代码中成为pandas-y而不是在可能的情况下编写循环.但我没有找到将系列转换为数据帧的魔力,这是我第一次尝试使用apply.
在此先感谢 - 古代C程序员
我假设这df_geo是一个单列的df所以我认为以下应该有效:
更改:
return lat, lon
Run Code Online (Sandbox Code Playgroud)
至
return pd.Series([lat, lon])
Run Code Online (Sandbox Code Playgroud)
那么你应该能像这样分配:
df_geo_in[['LAT', 'LON']] = df_geo_in.apply(locate)
Run Code Online (Sandbox Code Playgroud)
您尝试做的是将结果分配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')
Run Code Online (Sandbox Code Playgroud)
这将创建一个带有地理位置地址的非重复国家的df,然后我们执行左合并回主df.