2015-03-31 22 views
6

OK, jestem na pół-dowcipnym końcu. Geokoduję ramkę danych za pomocą geopii. Napisałem prostą funkcję do wprowadzania danych wejściowych - nazwa kraju - i zwracam szerokość i długość geograficzną. Używam apply do uruchomienia funkcji i zwraca obiekt serii Pandas. Nie mogę przekonwertować go na ramkę danych. Jestem pewien, że brakuje mi czegoś oczywistego, ale jestem nowy w pythonie i wciąż RTFMing. BTW, funkcja geocoder działa świetnie.Pandy Pandy "Zastosuj" zwraca serie; nie mogę przekonwertować na ramkę danych

# 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 

Próbowałem też

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

uzyskać pojedynczy dataframe bez indeksu i jednym colume z serii w nim.

Próbowałem kilka innych metod, w tym „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) 

który zwrócił błąd po długim czasie:

ValueError: Columns must be same length as key

Próbowałem zostały również ręcznie przez konwersję serii do ramki danych przy użyciu metody df.from_dict(df_geo_in) bez powodzenia.

Celem jest geokodowanie 166 unikalnych krajów, a następnie dołączenie ich do adresów 188K w df_addr. Próbuję być pandy-y w moim kodzie i nie zapisywać pętli, jeśli to możliwe. Ale nie znalazłem magii, aby przekształcić serie w ramki danych i to jest pierwszy raz, kiedy próbowałem użyć, aby zastosować.

góry dzięki - starożytny programista C

+0

co mówi typ (df_geo_in) w różnych punktach? czy to jest ramka danych? lub seria? w każdym razie możesz chcieć df_geo_in.fromdict() ?? df nie ma znaczenia, chyba że je zdefiniowałeś. Być może potrzebujesz pd.DataFrame (df_geo_in) – dartdog

Odpowiedz

7

Jestem zakładając, że df_geo jest df z jednej kolumnie więc wierzę dodaje powinno działać:

zmiana:

return lat, lon 

do

return pd.Series([lat, lon]) 

następnie powinieneś móc przypisać w ten sposób:

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

Co próbowałeś zrobić, to przypisać wynik applymap do 2 nowe kolumny, która jest błędna tutaj jako applymap jest przeznaczony do pracy na każdym elemencie w df więc chyba LHS ma ten sam oczekiwany kształt tego nie da pożądany wynik.

Twoja ostatnia metoda jest również niepoprawna, ponieważ upuszczasz zduplikowane kraje, a następnie oczekujesz, że przypiszesz każdemu krajowi geolokację, ale jej kształt jest inny.

Prawdopodobnie jest szybsza dla dużych df do tworzenia Geolokalizacja non-powielane df, a następnie scalić ten z powrotem do większych df tak:

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

to stworzy df z krajami spoza kopiowane z położenia geograficznego adresy, a następnie wykonujemy lewe połączenie z powrotem do głównego df.

+0

Dziękujemy! To rozwiązało! Teraz muszę tylko zrozumieć, dlaczego. – Harvey

0

Zawsze łatwiej testować niektóre przykładowe dane, ale proszę spróbować następujących funkcji pocztowy, aby sprawdzić, czy to działa.

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