Дополнительно
Быстрое Приближение Гаверсинус (На Python/Панды)
Каждая строка таблицы данных содержит панды широта/СПГ координаты 2-х точек. С помощью кода на Python ниже, вычисления расстояния между 2 точками для многих (миллионы) строк занимает очень много времени!
Учитывая, что 2 очка в 50 миль, и точность не очень важна, можно ли сделать расчет быстрее?
from math import radians, cos, sin, asin, sqrt
def haversine(lon1, lat1, lon2, lat2):
"""
Calculate the great circle distance between two points
on the earth (specified in decimal degrees)
"""
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
# haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * asin(sqrt(a))
km = 6367 * c
return km
for index, row in df.iterrows():
df.loc[index, 'distance'] = haversine(row['a_longitude'], row['a_latitude'], row['b_longitude'], row['b_latitude'])
31
6
Вот версия включает в себя векторные функции:
Входы всех наборов значений, и он должен уметь делать миллионы точек мгновенно. Требование заключается в том, что входы ndarrays а столбцы таблицы панды будет работать.
Например, с случайно сгенерированных значений:
Или если вы хотите создать еще один столбец:
Циклы по массивам данных происходит очень медленно в Python. Numpy содержит функции, которые работают на всю массивы данных, что позволяет избежать зацикливания и значительно повысить производительность.
Это пример векторизация.
Чисто ради примера, я взял и NumPy версия в ответ от @ballsdotballs и товарищ Си через
под
. Таквключает в себя
такой оптимизированный инструмент, есть небольшой шанс, что мой код на C будет работать так эффективно, но оно должно быть достаточно близко. Большим преимуществом здесь является то, что, запустив пример с типами, он может помочь вам увидеть, как вы можете подключить свой личный C функции в Python без особых накладных расходов. Это особенно приятно, когда вы просто хотите оптимизировать небольшой кусок побольше вычислений, написав, что небольшой кусок в некоторых с источника, а не питона. Просто с помощьювключает в себя
решит проблему, но для тех случаев, когда вы не't действительно нужно все библиотеки numpy и вы Don'т хотите, чтобы добавить соединение требует использованиявключает в себя
типы данных в течение некоторого кода, это'ы очень полезно знать, как опуститься в встроенной под библиотеку и сделать это самостоятельно.Сначала позвольте's создавать наши c исходный файл, называемый
гаверсинус.с
:в
Обратите внимание, что мы'вновь пытается сохранить с конвенций с. Явно передавая данные доводы со ссылкой, используя
реализация
для переменной размер, и ожидая нашгаверсинус
функции для работы с мутирующими один из переданных входами, так что он будет содержать ожидаемые данные на выходе. Функция на самом деле возвращает целое число, которое является успех/флаг неудач, которые могут быть использованы другими c-уровня потребителей функции.Мы'вновь придется найти способ, чтобы обработать все эти маленькие с конкретных вопросов внутри питона.
Далее, позвольте'ы поставили нашей библиотеки numpy версия функция вместе с некоторым импортом и некоторые тестовые данные в файл
haversine.py
:Я решил сделать лат и Лон (в градусах), которые выбираются случайным образом между 0 и 50, но это вовсе'т имеет значения слишком много для такого объяснения.
Следующее, что нам нужно сделать, это скомпилировать модуль c таким образом, что она может быть динамически загружен в Python. Я'м через системы Linux (вы можете найти примеры для других систем очень легко в Гугле), поэтому моей задачей является компиляция
гаверсинус.С
в разделяемый объект, вот так:Мы также можем скомпилировать в исполняемый файл и запустить его, чтобы увидеть, какие программы c's в функции
main
отображает:Теперь, когда мы собрали гаверсинус общий объект
.таким образом, мы можем использовать
под`, чтобы загрузить его в Python и нам нужно указать путь к файлу для этого:Теперь haversine_lib.акты гаверсинус довольно много, почти как функция Python, за исключением того, что мы, возможно, должны сделать некоторые ручного типа маршалинга, чтобы убедиться, что входы и выходы будут интерпретироваться правильно.
включает в себя
действительно обеспечивает некоторые хорошие инструменты для этого, и я'будете использовать здесь и NumPy.ctypeslib. Мы'ре собирается построить *указатель типа*, что позволит нам пройти вокруг и NumPy.ndarrays
этихпод
-загружен функции, как они были указатели. Здесь'ы код:Обратите внимание, что мы говорим `haversine_lib.функции прокси-гаверсинус интерпретировать свои доводы по видам мы хотим.
Теперь, чтобы проверить его из кожи питона то, что остается, это просто сделать размер переменная, а массив, в котором будут мутировавшие (как в коде C) должна содержать данные результата, то мы можем назвать:
Собираем все вместе в блок _основной ___ о `haversine.py теперь весь файл выглядит так:
Чтобы запустить его, который будет работать и времени на Python и
под
версии и отдельно печатать некоторые итоги, мы можем просто сделатькоторый отображает:
Как и ожидалось,
включает
версия немного быстрее (0,11 секунды для векторов длины 1 млн.), Но наши быстрые и грязные версии под `не сутулиться: респектабельный 0.148 секунд на одни и те же данные.Позвольте'ы сравните это с наивной цикл принятия решений в Python:
Когда я положил это в один и тот же файл в Python, как и другие, и времени на тот же миллион-элемент данных, я постоянно вижу время около 2.65 секунд на моей машине.
Поэтому, быстро переходя на
ПОД
мы повышаем скорость примерно 18. Для многих расчетов, которые могут извлечь выгоду из доступа к голой, непрерывных данных, вы часто видите доходы гораздо выше, чем даже это.Просто супер понятно, я нисколько не одобряя это как лучший вариант, чем просто с помощью
включает в себя
. Это как раз и проблема, чтовключает в себя
был построен, чтобы решить, и поэтому домашнего пивоварения свой собственныйпод
код всякий раз, когда он (а) имеет смысл включитьвключает в себя
типы данных в ваше приложение и (B) существует простой способ, чтобы сопоставить свой код Ввключает в себя
эквиваленте, это не очень эффективно.Но это's по-прежнему очень полезно знать, как сделать это для тех случаев, когда вы предпочитаете писать что-то в C еще называют это в Python, или ситуаций, когда зависимость от
включает в себя
- это не практично (во встроенной системе, гдевключает в себя
не может быть установлен, например).В случае, если через пакет scikit-учиться разрешено, я бы дал следующие возможности:
Тривиальное расширение @derricw'ы векторизированный Решение Вы можете использовать
numba
для повышения производительности в ~2 раза практически без изменения кода. Для чисто численных расчетов, это должно, вероятно, быть использован для сравнения / тестирования и, возможно, более эффективные решения.Бенчмаркинг по отношению к функции панд:
Полный код бенчмаркинга:
Функция векторизации указывает, что "все аргументы должны быть равной длины и". Расширяя границы в "больших" в наборе данных, согласно это, можно эффективно найти расстояние всех i,j в пар элементов.
Некоторые из этих ответов на "закругления" и радиус Земли. Если вы проверить их с другого расстояния калькуляторов (таких как geopy), эти функции будут отключены.
Вы можете переключиться из Р=3959.87433 для преобразования постоянного ниже, если вы хотите получить ответ в милях.
Если вы хотите километрах, используйте
Р= 6372.8
.