Geo data in Python

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Понадобилось мне недавно нарисовать в Python данные на карте, благо в данных есть координаты. Казалось бы, что может быть сложного... Но обо всем по порядку.

Мои точки - это города. Города имеют разные признаки, как качественные (используем разные цвета точек на карте), так и количественные (используем разный размер кружочка).

Первым делом нужно установить и импортнуть библиотеку geopandas - она показалась мне самой простой и понятной среди всех вариантов работы с геоданными.

import geopandas as gpd

Нужно нарисовать контуры России. Для этого нужен файл с границами - geojson. Его можно очень быстро нагуглить (я взяла отсюда). Мне нужны лишь контуры страны, поэтому я взяла файл 2 уровня - admin_level_2.geojson

Этот файл нужно прочитать в dataframe. Так как у меня jupyterhub поднят на сервере, мне понадобилось сначала файл загрузить в jh. Далее конвертируем его в GeoDataFrame и отрисовываем. Получился следующий код.

map_df=gpd.read_file('my_env/admin_level_2.geojson') 
map_df=gpd.GeoDataFrame(map_df) 
map_df.plot(figsize=(14,10), color='black', alpha=0.1)

3 простых шага, которых достаточно достаточно почти в любой стране мире. Но есть одно "но" - Россия реально большая страна.

Настолько большая, что переходит границу 180о и из-за этого стандартная отрисовка рисует бедный дальневосточный кусок не справа, а далеко слева.

Поэтому сначала нужно сделать преобразование координат, прибавив к оторвавшемуся куску 360о.

Я рассмотрела файл поближе и выяснила, что он состоит из 29 полигонов. Прибавить к нужным полигонам 360о - дело не сложное. Запихиваем в цикл по датафрейму и сдвигаем полигоны с отрицательными координатами.

Но нет. Тут мой код зависал всерьез и надолго. Геоданные - огромный тяжелый массив и перелопачивать их все jh явно не желал. Недолго думая я приняла решение пожертвовать Кемской волостью мелкими полигончиками.

Я отрисовала все полигоны по отдельности и выяснила, что основная часть - это полигон 28. Отрезанный кусок дальнего востока - 26. Сдвинуть один на 360о и отрисовать только эти два полигона занимает буквально секунду. Итоговый код занимает 5 строчек, а результат вполне меня устраивает.

map_df=gpd.read_file('my_env/admin_level_2.geojson') 
map_df=gpd.GeoDataFrame(map_df)
p = gpd.GeoSeries(shapely.affinity.translate(map_df['geometry'][0][26], xoff=360, yoff=0))
p=p.append(gpd.GeoSeries(map_df['geometry'][0][28]))
p.plot(figsize=(14,10), color='black', alpha=0.1)

Теперь займемся данными, ради которых мы всё это начали. Не забываем, что в выгружаемых данных тоже возможно есть данные с отрицательными координатами и их так же надо сдвинуть на 360 для нормальной отрисовки.

select city
		,lat
    ,case when lon<0 then lon+360 else lon end as lon
    ,category
    ,qty
from my_table

Преобразуем поля широты и долготы в одно поле "координаты" и преобразуем DataFrame в GeoDataFrame.

df['coordinates'] = df[['lon', 'lat']].values.tolist()
df['coordinates'] = df['coordinates'].apply(Point)
df = gpd.GeoDataFrame(df, geometry='coordinates')

Всё. Осталось только нарисовать оба набора данных вместе. Важно помещать обе строки в одну ячейку jupyterhub'а, иначе не сработает.

ax_all=p.plot(figsize=(14,10), color='black', alpha=0.1)
df.plot(ax=ax_all, column = 'category',markersize=20,marker='o')

Или пример с размером кружочков (на урезанном наборе данных для наглядности).

ax_all=p.plot(figsize=(14,10), color='black', alpha=0.1)
df_size.plot(cmap='autumn',ax=ax_all, markersize='qty',marker='o',alpha=0.6)

Далее можно наводить красоту, но основная задача выполнена. Кроме того этого вполне достаточно для быстрого анализа данных, а именно это нам обычно и нужно от Python.

Источник: https://habr.com/ru/post/655395/


Интересные статьи

Интересные статьи

К старту флагманского курса по Data Science делимся сокращённым переводом из блога RealPython о трюках с Pandas, материал начинается с конфигурирования запуска библиотеки и заканчиваются примерами раб...
В середине 2020 года в СИБУРе запустился проект, направленный на автоматизацию процесса лидогенерации (поиска потенциальных клиентов). Вызов состоял в том, что в B2B, а особенно промышленности и произ...
Привет, Хабр! Я Слава, руководитель команды «Профессиональные инструменты» в Циане и член core-команды авторов в Яндекс.Практикуме. Вместе с ребятами мы развиваем курс «Мидл python-раз...
Наверняка, каждый, кто хоть раз писал что-то на Python, задумывался о том, как распространять свою программу (или, пусть даже, простой скрипт) без лишней головной боли: без необходимости устана...
Сегодня мы представляем открытую для тестирования бета-версию Managed Databases для PostgreSQL, использование которой будет бесплатным на период бета-тестирования. Базы данных — один из наиб...