Извлечение региона NUTS2 из геокоординат и / или почтового индекса - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть df, который содержит данные, включая геокоординаты и почтовые индексы.

lat     | lon  | postcode
54.3077 | 12.7 | 18314   
51.898  | 9.26 | 32676

Мне нужен новый столбец с регионом NUTS2, поэтому в этом случае результирующий df должен выглядеть примерно так:

lat     | lon  | postcode | NUTS_ID
54.3077 | 12.7 | 18314    | DE80
51.898  | 9.26 | 32676    | DEA4

Я нашел этот пакет: https://github.com/vis4/pyshpgeocode, который мне удалось запустить.Мой первый подход - это две следующие функции:

def get_gc(nuts='geoc\\shapes\\nuts2\\nuts2.shp'):
    """
    nuts -> path to nuts file
    """
    gc = geocoder(nuts, filter=lambda r: r['LEVL_CODE'] == 2)
    return gc
def add_nuts_to_df(df):
    """
    df must have lon/lat geocoodinates in it
    This function will add a column ['NUTS_ID'] with the corresponding
    NUTS region
    """
    start_time = time.time()
    for idx, row in df.iterrows():
        df.loc[idx, 'NUTS_ID'] = get_gc().geocode(row.lat,
                                                  row.lon,
              filter=lambda r: r['NUTS_ID'][:2] == 'DE')['NUTS_ID']
        print('Done with index {}\nTime since start: {}s'.format(idx,
              round(time.time() - start_time, 0 )))
    return df

И это работает!Однако для одной записи требуется ~ 0,6 с, а некоторые из моих df содержат более миллиона записей.Поскольку мои исходные кадры данных обычно содержат почтовые индексы, я думал об их агрегировании с использованием комбинации groupby / apply / transform?

Или есть ли другой (более эффективный) способ сделать это?

IЯ очень благодарен за любую помощь и с нетерпением жду ответов.

1 Ответ

0 голосов
/ 26 февраля 2019

Если я правильно понимаю ваш код, вы заново создаете объект gc для каждого отдельного запроса из одного и того же входного файла.Я не понимаю почему.

Поэтому одной из возможностей может быть следующее:

def add_nuts_to_df(df):
    """
    df must have lon/lat geocoodinates in it
    This function will add a column ['NUTS_ID'] with the corresponding
    NUTS region
    """
    nuts='geoc\\shapes\\nuts2\\nuts2.shp'
    gc = geocoder(nuts, filter=lambda r: r['LEVL_CODE'] == 2)

    start_time = time.time()
    for idx, row in df.iterrows():
        df.loc[idx, 'NUTS_ID'] = gc.geocode(row.lat,
                                                  row.lon,
              filter=lambda r: r['NUTS_ID'][:2] == 'DE')['NUTS_ID']
        print('Done with index {}\nTime since start: {}s'.format(idx,
              round(time.time() - start_time, 0 )))
    return df

Возможно, это ускорит процесс еще больше, если вы попытаетесь использовать метод df.apply() и передать логику геокода вфункция там.

Что-то вроде:

nuts='geoc\\shapes\\nuts2\\nuts2.shp'
gc = geocoder(nuts, filter=lambda r: r['LEVL_CODE'] == 2)

def get_nuts_id(row):
    return gc.geocode(row.lat, row.lon, 
                      filter=lambda r: r['NUTS_ID'][:2] == 'DE')['NUTS_ID']

df["NUTS_ID"] = df.apply(get_nuts_id,axis=1)

Я не пробовал это, хотя остерегайтесь опечаток.

...