Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Васильев Ю. - Python для data science (Библиотека программиста) - 2023.pdf
Скачиваний:
7
Добавлен:
07.04.2024
Размер:
7.21 Mб
Скачать

196      Глава 9. Анализ данных о местоположении

Рис. 9.1. Как поделиться информацией о местоположении в Telegram

Первое поле в каждой строке содержит имя пользователя, второе и третье поля хранят широту и долготу местоположения пользователя, а четвертое — метку времени. Для некоторых задач, например для поиска ближайшего автомобиля к определенному месту подачи, понадобится только последняя строка с данными об автомобиле. Однако для других задач, таких как расчет общего расстояния поездки, пригодятся несколько строк с информацией о машине, отсортированных по времени.

Анализ пространственных данных с помощью geopy и Shapely

Анализ пространственных данных сводится к ответам на вопросы о взаимосвязях: какой объект находится ближе всего к определенному месту? Находятся ли два объекта в одной области? В этом разделе мы ответим на эти вопросы пространственного анализа в контексте нашего примера службы такси. Для этого будем использовать две библиотеки Python — geopy и Shapely.

Анализ пространственных данных с помощью geopy и Shapely      197

Поскольку geopy предназначена для выполнения расчетов на основе геокоординат, она особенно хорошо справляется с ответами на вопросы о расстоянии. В свою очередь, Shapely специализируется на определении и анализе геометрических плоскостей, поэтому она идеально подходит, чтобы выяснить, попадает ли тот или иной объект в указанную область. Вы увидите, что обе библиотеки играют роль в определении самого подходящего автомобиля для конкретного заказа.

Прежде чем двигаться дальше, установим их:

$ pip install geopy

$ pip install shapely

Поиск ближайшего объекта

Продолжая пример со службой такси, рассмотрим, как использовать данные о местоположении для определения машины, ближайшей к месту подачи. Для начала нам понадобится образец данных о местоположении. Если вы развернули telegram-бота, о котором говорилось в предыдущем разделе, то возможно, у вас уже есть некоторые данные в виде CSV-файла. Во фрагменте кода ниже мы загружаем данные и преобразуем их в объект pandas DataFrame, чтобы их было легко сортировать и фильтровать:

import pandas as pd

df = pd.read_csv("HOME/PI/LOCATION_BOT/LOG.CSV", names=['cab', 'lat',

'long', 'tm'])

Если вы не развернули telegram-бота, можно создать список кортежей с примерами данных о местоположении и привести его к типу DataFrame следующим образом:

import pandas as pd locations = [

('cab_26',43.602508,39.715685,'14:47:44'), ('cab_112',43.582243,39.752077,'14:47:55'), ('cab_26',43.607480,39.721521,'14:49:11'), ('cab_112',43.579258,39.758944,'14:49:51'), ('cab_112',43.574906,39.766325,'14:51:53'), ('cab_26',43.612203,39.720491,'14:52:48')

]

df = pd.DataFrame(locations, columns =['cab', 'lat', 'long', 'tm'])

198      Глава 9. Анализ данных о местоположении

В обоих случаях у вас будет датафрейм df со следующими столбцами: идентификатор такси (cab), широта (lat), долгота (long) и метка времени (tm).

ПРИМЕЧАНИЕ

Есливыхотитесоздатьсвоисобственныеобразцыданныхсгеолокацией,тосамый

простой способ сделать это — найти координаты широты и долготы с помощью Google Maps. При щелчке правой кнопкой мыши места на карте координаты широты и долготы этой геолокации будут отображаться в первой строке меню.

Для каждого автомобиля в датафрейме содержится несколько строк, но для определения ближайшего к месту подачи автомобиля понадобятся только последние координаты машины. Отфильтровать ненужные строки можно так:

latestrows = df.sort_values(['cab','tm'],ascending=False).drop_duplicates('cab')

Здесь мы сортируем строки по полям cab и tm в порядке убывания. Эта операция группирует датасет по столбцу cab и помещает последнюю строку для каждой группы (автомобиля) на первое место. Затем мы применяем метод drop_duplicates() для удаления всех строк с данными об автомобиле, кроме первой. Итоговый датафрейм latestrows выглядит так:

 

cab

lat

long

tm

5

cab_26

43.612203

39.720491

14:52:48

3

cab_112

43.574906

39.766325

14:51:53

 

 

 

 

 

Теперь у нас есть датафрейм, содержащий только данные о последнем местоположении каждого такси. Для удобства дальнейших вычислений преобразуем датафрейм в более простую структуру Python — список списков. Таким образом легче добавлять новые поля в каждую строку, например поле для расстояния между такси и местом подачи:

latestrows = latestrows.values.tolist()

Свойство values датафрейма latestrows возвращает NumPy-представление датафреймa, которое мы затем преобразуем в список списков с помощью tolist().

Теперь можно рассчитать расстояние от места посадки до каждого автомобиля. Используем библиотеку geopy, с помощью которой эта задача решается всего

Анализ пространственных данных с помощью geopy и Shapely      199

несколькими строками кода. Во фрагменте кода ниже применим функцию distance() из модуля geopy для проведения необходимых расчетов:

from geopy.distance import distance pick_up = 43.578854, 39.754995

for i,row in enumerate(latestrows):

dist = distance(pick_up, (row[1],row[2])).m print(row[0] + ':', round(dist)) latestrows[i].append(round(dist))

Для простоты указываем место подачи, вручную задавая координаты широты и долготы. Однако на практике можно использовать Google Geocoding API для автоматической генерации координат из улицы и номера дома, как обсуждалось выше. Затем проходим по каждой строке датасета и вычисляем расстояние между каждым автомобилем и местом посадки с помощью вызова distance() . Эта функция принимает в качестве аргументов два кортежа с координатами широты и долготы. Добавив .m, мы получим расстояние в метрах. Чтобы посмотреть результат, выводим на экран каждое вычисленное расстояние, а затем добавляем его в конец строки как новое поле. Ниже представлен результат выполнения скрипта:

cab_112: 1015 cab_26: 4636

Очевидно, что cab_112 ближе, но как это определить программным путем? Для этого подойдет встроенная в Python функция min():

closest = min(latestrows, key=lambda x: x[4])

print('Ближайшая машина: ', closest[0], ' – расстояние в метрах: ', closest[4])

Передаем данные в min()и применяем лямбда-функцию, чтобы задать порядок сортировки строк по элементу с индексом 4. Таким образом мы добавим расчет расстояния. Выводим результат в формате, пригодном для чтения, и получаем:

Ближайшая машина: cab_112 - расстояние в метрах:

1015

 

 

В данном примере мы рассчитали расстояние по прямой между каждой машиной и местом подачи. Хотя эта информация, безусловно, полезна, в реальности автомобили почти никогда не ездят по идеально прямой линии. Фактическое