Как один мужик карту города рисовал
Всем привет!
Сегодня поговорим о визуализации геоданных с помощью GeoPandas и Kepler.gl. Хотел бы рассказать, как я за пару дней построил вот такую карту, где высота полигонов регулировалась этажностью здания, а цвет — годом постройки.
Нижний Новгород
Постановка задачи
Когда я работал 2 года назад (август 2020) в одной нижегородской компании, ко мне пришёл мой начальник и сказал, что мне надо визуализировать аварийные и старые дома в нашей области. Мне прислали .excel файл, где был указан адрес дома, количество этажей, год постройки и признак аварийности.
address | floor_count_max | built_year | is_alarm |
д. г Навашино ул Соболева д. 1 | 2 | 1954 | Нет |
обл. Нижегородская, р-н. Ардатовский, рп. Ардатов, ул. 1 Мая, д. 32 | 5 | 1977 | Нет |
Геопроцесинг
Окей, подумал я. Стажировка в Яндекс.Картах не прошла даром, я знал о существовании такого сервиса, как Яндекс.Геокодер. Координаты я получу, останется нарисовать это где-нибудь. (О нем знали все в Картах, это было наше самое узкое место на тот момент. Инструмент очень важный и полезный для большинства сервисов, поэтому на команды был выделен строгий трафик).
Не тут-то было. Геокодер имеет жесткие бесплатные условия использования API Яндекс.Карт. Ранее число бесплатных запросов было порядка 20к, но сейчас уже давно 1к. Я стал искать ещё варианты.
Как посоветовали в статье про геокодирование, я использовал OSM геокодер. И взял на заметку комментарий, что проблемные случаи можно отправлять в Яндекс, поскольку для России, конечно же, Яндекс выдает более точные результаты. Но в текущей реализации я вообще не следил за качеством данных геокодирования и качеством сырых данных. Мне было интересно поскорее уже что-нибудь нарисовать.
И тут я наткнулся на классный инструмент — Kepler.gl. Прочитал пару постов на Хабре (раз, два) и понял что это то, что мне нужно. Я загрузил свою табличку, уже с координатами, и получил такой результат.
Я был в восторге, можно было выбирать колонки, отвечающую за высоту (этажность) и цвет (год постройки / аварийность). Цвет можно было задать тепловой картой. Интерфейс был интуитивный. Правда, вместо домов торчали столбики. Я показал это начальнику, он мне ответил, что в целом наглядно, но на серьезных мероприятиях такое показывать нельзя. Я немного расстроился, но продолжил искать пути улучшения.
Полигоны
Я понял, что мне нужно скачать 2d полигоны, но не знал где их взять, пока не наткнулся на замечательный пост. Достаточно было скачать с http://download.geofabrik.de/ свой округ и вырезать Нижегородскую область.
Далее началось самое интересное. В данных OSM уже была информация об этажах, но не везде. И не было информации о годе постройки и аварийности. Мне предстояло соединить файл с полигонами с табличкой с координатами и адресами. Я стал судорожно гуглить, как определить принадлежность точки к полигону. Реализовав простейший алгоритм, я стал запускать расчёты. План был следующий, для каждой точки координат я пытался найти полигон, в котором она лежит. Получился вложенный цикл. Количество полигонов было порядка 600,000, а количество адресов с координатами было 22,000. Можно было сделать сортировку по Долготе/Широте и немного сократить длину перебора, используя бинарный поиск. Но было всё равно ужасно долго. Подождав ± 10 часов, я получил результат. И так у меня это всё и работало до недавнего времени.
Пока я не наткнулся на интересную статью, в рамках подготовки к данному посту. Моя задача решалась одним джойном с использованием GeoPandas. Время выполнения стало 2 секунды. И ещё пару огромных плюсов заключается в том, что датафрейм можно сохранять сразу в .geojson, а не мучиться с конвертированием обычного .json. А исходный файл можно загружать сразу из .shp формата, который выдает геофабрика.
Советую всем использовать GeoPandas, это замечательный инструмент, я имел опыт работы с ним в университете, но совершенно забыл про него.
Результат матчинга на картинке. Точки уверенно попадают в полигоны.
Результат
В итоге у меня получилась отличная интерактивная карта, где у каждого дома есть своя табличка с информацией. Карту можно крутить, раскрашивать, менять фон. Kepler.gl можно кастомизировать. Карту в формате .html можно сохранить и отправить другим людям. Карта присутствует в репозитории.
Видно, что много пустых полигонов. Бороться с этим можно с помощью улучшения качества сырых данных и геокодирования.
Что дальше?
Я уже составил гениальный план, что в карточки к домам можно добавлять информацию о доме, архитектуре, жильцах, различные фотографии. Но понял, что не изобрету ничего лучше существующих карт. А идею с реализацией раскраски полигонов уже выложили на Хабр 3 месяца назад в замечательном посте с красивыми постерами городов. Используются немного другие инструменты, но суть такая же.
Поэтому пришлось всё отложить в долгий ящик, пока я не нашёл время рассказать эту историю. А свою задачу тогда я выполнил.
Реализация
Прикрепляю ссылку на GitHub, где есть все исходные данные, итоговая карта и .ipynb файлы для личного повторения моего пути.
Спасибо
Приезжайте гулять в Нижний Новгород