Python повторение через Pandas DataFrame и добавление новых значений, рассчитанных с помощью geopy.geocoders Предложения по производительности Nominatim - PullRequest
1 голос
/ 27 мая 2020

У меня есть файл .csv с несколькими миллионами строк. Строки содержат данные о местоположении (название улицы), и я пытаюсь преобразовать это название улицы в долготу и широту, пытаясь провести некоторый географический анализ. Проблема заключается в том, что для обработки одной строки требуется около 0,5 с.

Я попытался улучшить свой код с помощью динамического c программирования и сохранения уже рассчитанных значений в словаре, чтобы я мог их повторно использовать, но это только уменьшило время, необходимое для вычисления одной строки, примерно до 0,3 с.

Название улицы довольно часто повторяется, и когда я нахожусь примерно в 1000-й строке, я получаю около 50% совпадений из словаря, к сожалению, это все еще кажется слишком медленным. Если у кого-то есть идея, как я могу улучшить этот код, я все слышу, так как текущий код более или менее бесполезен, так как для перебора всех строк потребуется неделя.

Мой текущий код выглядит следующим образом :

def long_lat_to_csv(dataset, output_file):
    dataset['longitude'] = None
    dataset['latitude'] = None
    geolocator = Nominatim(user_agent="test")
    longlat  = dict()
    area = "New York City, USA"
    for i, row in dataset.iterrows():
        if int(i) % 100 == 0:
            print('current row:', i)
        address = row['Street Name']
        try:
            # if address already calculated:
            long, lat = longlat[address]
            dataset.at[i, 'longitude'] = long
            dataset.at[i, 'latitude'] = lat
        except:
            # if address isn't calculated yet
            try:
                loc = geolocator.geocode(address + ',' + area)
                longlat[address] = [loc.longitude, loc.latitude]
            except:
                # also store addresses that return None
                longlat[address] = None

    dataset.to_csv(output_file, index=False)

1 Ответ

1 голос
/ 27 мая 2020

Итерация по кадру данных с помощью iterrows - удобный метод, но имеет очень низкую производительность.

Здесь вам следует:

  1. извлечь уникальные адреса из исходного DataFrame
  2. вычисляет географические координаты этих уникальных адресов (временно забудьте о pandas здесь)
  3. используйте merge, чтобы скопировать эти координаты обратно в исходный DataFrame

It может стать:

geolocator = Nominatim(user_agent="test")
area = "New York City, USA"

addresses = dataset['Street Name'].drop_duplicates()
addresses = pd.concat(addresses,
                      pd.DataFrame([loc.longitude, loc.latitude] for address in addresses
                                    for loc in [geolocator.geocode(address + ',' + area)]],
                                   index=addresses.index, columns=['longitude', 'latitude']))  

dataset = dataset.merge(addresses, on=['Street Name'])
dataset.to_csv(output_file, index=False)
...