2015-03-31 16 views
6

好吧,我在半智機的末端。我使用geopy對數據框進行地理編碼。我寫了一個簡單的函數來輸入國家名稱 - 並返回經度和緯度。我使用apply來運行該函數,並返回一個Pandas系列對象。我似乎無法將其轉換爲數據框。我敢肯定,我錯過了一些明顯的東西,但我對Python很陌生,仍然RTFMing。順便說一句,地理編碼器功能很好。Python Pandas'apply'returns系列;不能轉換爲數據幀

# 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) 

我得到一個數據幀,沒有指標,並在它的系列單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) 

其中長的時間後返回錯誤:

ValueError: Columns must be same length as key

我也嘗試手動轉換使用df.from_dict(df_geo_in)方法將數據序列轉換爲數據幀,但沒有成功。

目標是對166個獨特國家進行地理編碼,然後將其加入df_addr中的188K地址。我試圖在我的代碼中擔任pandas-y,如果可能的話不要寫循環。但我還沒有找到將系列轉換爲數據框的魔力,這是我第一次嘗試使用apply。

在此先感謝 - 古老的C程序員

+0

什麼類型(df_geo_in)在不同點說?它是一個數據幀嗎?或一系列?無論如何,你可能想要df_geo_in.fromdict()? df沒有意義,除非你定義了它..你可能需要pd.DataFrame(df_geo_in) – dartdog 2015-03-31 02:46:58

回答

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的然後合併這回你更大的自由度,像這樣:

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。

+0

謝謝!這解決了它!現在我只需要更好地理解爲什麼。 – Harvey 2015-03-31 15:32:14

0

總是更容易一些樣本數據來檢驗,但請嘗試以下壓縮功能,看它是否工作。

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