Python Pandas 'apply' returns 系列;无法转换为数据框
Python Pandas 'apply' returns series; can't convert to dataframe
好吧,我已经傻眼了。我正在使用 geopy 对数据框进行地理编码。我编写了一个简单的函数来获取输入 - 国家名称 - 和 return 纬度和经度。我使用 apply to 运行 函数,它 return 是一个 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)
return长时间后出现错误:
ValueError: Columns must be same length as key
我也尝试过使用 df.from_dict(df_geo_in)
方法手动将系列转换为数据框,但没有成功。
目标是对 166 个独特的国家/地区进行地理编码,然后将其加入 df_addr 中的 188K 个地址。我试图在我的代码中成为 pandas-y 并且尽可能不编写循环。但是我还没有找到将系列转换为数据帧的魔法,这是我第一次尝试使用应用。
提前致谢 - 古老的 C 程序员
使用一些示例数据总是更容易测试,但请尝试以下 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)
我假设 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。
好吧,我已经傻眼了。我正在使用 geopy 对数据框进行地理编码。我编写了一个简单的函数来获取输入 - 国家名称 - 和 return 纬度和经度。我使用 apply to 运行 函数,它 return 是一个 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)
return长时间后出现错误:
ValueError: Columns must be same length as key
我也尝试过使用 df.from_dict(df_geo_in)
方法手动将系列转换为数据框,但没有成功。
目标是对 166 个独特的国家/地区进行地理编码,然后将其加入 df_addr 中的 188K 个地址。我试图在我的代码中成为 pandas-y 并且尽可能不编写循环。但是我还没有找到将系列转换为数据帧的魔法,这是我第一次尝试使用应用。
提前致谢 - 古老的 C 程序员
使用一些示例数据总是更容易测试,但请尝试以下 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)
我假设 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。