Привет, я Катя, системный аналитик в Ozon. Одна из первых задач, которую мне поручили здесь — проверить качество географических данных. Формально эта задача больше относится к анализу данных, чем к системному анализу. Но меня она очень заинтересовала, ведь требовался не только анализ, но и исследование и, по возможности, реализация решения, а для меня это самое интересное в работе.  Впереди меня ждала RnD-задача с исследованием картографических форматов, рисованием поверх Google Maps и реализацией скрипта на Python. Как я боролась с визуализацией картографических данных, расскажу в этой статье. У нас в Ozon есть сервис, который по переданной координате определяет населённый пункт. Это своего рода обратное геокодирование.  Время от времени от коллег из поддержки нам прилетали сообщения о том, что сервис некорректно определяет населённый пункт. Например, на картах Яндекса координаты соответствуют Алматы, а наш сервис считает, что это Баганашыл. Забегая вперед, покажу, как выглядели данные по Алматы в нашем сервисе. Пришло время проверить корректность географических данных, хранящихся в нашей системе. Данные для нашего сервиса мы храним в PostrgreSQL с расширением PostGIS, которое позволяет работать с географическими объектами. Для определения населенного пункта нужны: его название, координата центра и геометрия, обозначающая его границы (полигон или мультиполигон). Населённый пункт мы определяем по вхождению переданной координаты в геометрию. Если не нашли, то ищем ближайшую координату центра. Определение населённого пункта по вхождению точки в геометрию является самым точным методом, но есть важная деталь: данные должны быть корректными. В нашем случае именно корректность данных по полигонам стала проблемой. Эти данные копились в системе в течение всей её жизни. Что-то вносили вручную, что-то унаследовано из других систем,  Раз речь о картах — наглядной информации, то для проверки корректности данных мы решили их визуализировать. Задачей было нанести полигоны и координаты центров городов поверх реальной карты и визуально оценить, насколько всё хорошо или плохо. У нашего сервиса нет пользовательского интерфейса, поэтому для визуализации географических данных нам нужен был сторонний инструмент с возможностью импорта данных. Такая возможность есть у обоих «главных» картографических сервисов — Google Maps и Яндекс.Карт.   К слову, лично мне больше понравился импорт Google Maps: интуитивно понятнее, подробнее сообщает об ошибках, штатно позволяет загружать координаты точек без формирования CSV-файла по жёсткому шаблону.  И Google Maps, и Яндекс.Карты позволяют с помощью CSV-файла отобразить на карте объекты по их координатам. Однако, чтобы загрузить более сложную геометрию (полигоны, мультиполигоны, линии), нужно иметь файл специфического картографического формата.   Google Maps поддерживает импорт в следующих форматах: CSV и XLSX — для отображения координат точек,  GPX — для маршрутов,  KML — для любых географических объектов.   У Яндекс.Карт похожий список. Разница лишь в том, что нет GPX, но есть GeoJSON, который по назначению аналогичен KML.   Мой выбор пал на формат KML.  Основная причина, по которой я выбрала KML для импорта данных на карты, заключалась в том, что этот формат поддерживают и Google, и Яндекс. Правда, как позже показала практика, бывают файлы с полигонами, которые отображаются на Google Maps, но не видны на Яндекс.Картах (но тогда мне ещё только предстояло это выяснить).  Ещё KML — это язык разметки на основе XML, так что я подумала, что сформировать такой файл будет не очень сложно. У KML много возможностей — он даже позволяет отрисовывать 3D-объекты. Для решения моей задачи оказалось достаточно пяти элементов: Placemark — объект, позволяющий задавать геометрию (от координаты точки до мультиполигонов). Multigeometry — контейнер для нескольких геометрических примитивов, связанных с одним и тем же географическим объектом (например, для координаты центра и полигона). Polygon — многоугольник области; может дополнительно содержать внутреннюю вырезанную область. Мультиполигоны для отображения разбиваются на полигоны. Point — географическое местоположение, определяемое долготой и широтой. Координаты следуют в таком порядке: сначала долгота, потом широта. Style — стиль представления геометрии (например, цвет). Пример структуры файла для отображения одного объекта, состоящего из точки и полигона: Файл из тысяч элементов не хочется формировать вручную. С генерацией KML-файлов мне помогла Python-библиотека pyKML. Я написала небольшой скрипт: на вход он принимает XLSX-файл с данными о географических объектах. Структура файла – четыре колонки: наименование, описание, координата точки, геометрия в текстовом формате WKT (может быть пустой). На выходе формируется KML-файл, который можно использовать для отображения своих объектов на картах.  На всякий случай предупрежу: у Google Maps есть ограничение по количеству импортируемых объектов в 2000 штук. Если нужно отобразить больше, то придётся сделать несколько файлов. Помните, как выглядел Алматы на карте в начале статьи? Несколько точек и только одна из них принадлежала непосредственно городу Алматы, остальные являлись районами, улицами, парками, в общем, не являлись населенными пунктами. Имея дело с такими данными, наш сервис в большинстве случаев ошибался (у Алматы не было полигона, поэтому алгоритм находил не сам город, а ближайшую точку, которая по факту городом не является). А вот так Алматы преобразился после обновления данных. Теперь есть полигон и можно быть уверенными, что всё множество точек, входящих в границы города, будет определяться правильно. Такая визуализация помогает увидеть проблемные места и убедиться в корректности данных после обновления.  Google Maps предоставляет отличные возможности для отображения географических данных без каких-либо серьёзных дополнительных манипуляций. Для визуализации в виде «было — стало» сервис подходит отлично, на мой взгляд: можно наглядно убедиться в корректности географических данных.  Когда может не подойти такой подход, и потребуется привлекать тяжёлую артиллерию— разработчиков? Предположим, у вас есть данные о движении грозовых фронтов, и вы хотите показывать их пользователю в режиме реального времени. В этом случае импорт файлов на карту вручную не подойдёт. Однако предполагаю, что формирование KML-файлов для решения этой задачи тоже может пригодиться: вы сможете встроить в своё приложение карту и отрисовывать данные уже программным способом.    Как всегда, это история о балансе: сделать быстро или основательно, разбираться самостоятельно или обратиться за помощью, следовать инструкции или интуиции. Когда вам в следующий раз придётся делать такой выбор, надеюсь, моя история не будет вас перетягивать на одну из сторон, но напомнит: иногда вы можете больше, чем сами от себя ожидаете.  И конечно, желаю вам качественных данных и успехов в их визуализации! Импорт данных на Google Maps  Импорт данных на Яндекс.Карты Документация по KML от Google pyKML: Python-библиотека для формирования KML-файлов  WKT: формат представления векторной геометрии и описания систем координат xslx2kml: мой скрипт для создания KML-файлов на основе XLSX-файлов с данными о географических объектах Системный аналитик