Геокодирование в Open Refine

получаем координаты из адресов

Kats Philipp
DADA science
Published in
7 min readNov 25, 2013

--

Одна из функций Refine (далее OR) — создание дополнительных значений в таблице на основе http-запросов. Фактически функция может быть использована в двух целях:

  1. Скрейпинг данных со страниц. Для этого можно, к примеру, создать табличку с сылками на схожие страницы, и последовательно собрать с них данные. В GREL (внутренний язык для OR, очень схожий с Python) для этого случая существует специальные функции, — parseHtml, select, htmlAttr, htmlText и др.
  2. Обращение к API через http-запрос. Запрос может быть любой, например к этим сервисам.

Одна из наиболее частых задач, решаемых с помощью API — геокодирование.

Геокодирование — определение координат локации по адресу и наоборот ( обратное геокодирование).

Услуги геокодирования предоставляют все основные картографические сервисы (Google Maps, Yandex maps, OSM) и другие фирмы (существует ряд тонкостей, связанных с точностью и технологией геокодирования, например геокодирование по словаря топонимов, такие услуги обеспечивают специализированные сервисы).

Примечание: Для быстрого геокодирования существует уникальный сервис Google Fusion Tables, позволяющий автоматически расставить точки адресов на карте без указания координат. Однако у сервиса есть сильные ограничения: его невозможно настроить, а главное, через него невозможно заполучить сами координаты. Оба ограничения не позволяют считать Fusion полноценным геокодером.

Каждый сервис налагает свои лицензионные и технические требования.

В этом примере я пользуюсь сервисом Yandex, обладающим, по всей видимостью, одной из лучших баз адресов по России,и большим лимитом на количество запросов (25000 в день, для сравнения лимит Google — 2500 в день). Вместе с тем, Яндекс налагает ряд ограничений, поэтому для коммерческого использования может быть удобнее использовать сервис OSM (впрочем, этот сервис тоже требует указание источника).

I. Подготовка

Итак, для обращения к сервису мы будем использовать адреса велопарковок города Москвы.Набор данных лежит здесь. Для начала, загрузим данные в OR.

Файл в OR после удаления ненужных столбцов

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

  1. В первой колонке должен стоять только номер, cлова “Велосипедная парковка” и адрес здесь излишни.
  2. Адрес во второй колонке описательный (“Вблизи входа в парк Музеон”), что хорошо для человека,но будет мешать геокодированию. Намного более нам подходит формальный адрес в первом столбце.

Следовательно, мы удаляем ненужное в первой колонке, адрес выделяем в отдельную колонку. Для этого мы используем команды Transform cell и Split column into several columns соответственно:

Удаление лишних слов. Команда Edit Cell>transform
Разделение столбца на два отдельных. В данном случае делителем будет работать пробел, а число столбцов ограничено двумя (срабатывает только первый пробел)

После таких трансформаций мы получаем следующую структуру данных: номер парковки, формальный адрес парковки, неформальный адрес, вместимость.

В принципе, все готово для геокодинга, однако мы можем несколько упростить для компьютера задачу…

Важно понимать, что геокодинг — процесс, сама технология которого допускает определенный уровень погрешности

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

Присоединение названия города к адресу

Теперь мы точно готовы к геокодингу. Что нам для этого нужно?

II. Параметры геокодирования

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

Итак, первое что мы видим — базовый запрос:

http://geocode-maps.yandex.ru/1.x/?geocode=Москва,+Тверская+улица,+дом+7

Какие дополнительные параметры стоит указать в геокодировании? Во-первых, давайте определим тип ответа. OR умеет разбирать json-файлы, так что давайте использовать этот формат:

format=json

Для уточнения зоны геокодирования мы можем включить ограничение области ответов:

rspn=1

В таком случае мы должны указать эти границы — центр зоны и диапазон допустимых значений относительно центра.

ll=37.618920,55.756994 (координаты Москвы)
spn=0.552069,0.400552 (диапазон)

Количество вариантов ответа, начиная с самого правдоподобного. Наши адреса достаточно простые, так что надеемся, что нам поведет:

results=1

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

key=API-ключ

III. Начинаем геокодирование

Определившись с параметрами, мы должны сформировать запрос целиком. Все параметры объединяются в одну строку знаком “&” . Первым идет адрес запроса, после этого очередность не важна. Для простоты, адрес мы будем указывать в самом конце. Должно получиться что-то типа того:

http://geocode-maps.yandex.ru/1.x/?format=json&rspn=1&ll=37.618920,55.756994&spn=0.552069,0.400552&results=1&geocode=

Обратите внимание, что в примере (начало предыдущего раздела) в адресе вместо пробела используется знак “+”. Мы и сами можем заменить его, но проще воспользоваться стандартной функцией подготовки текста для url:

escape(value, ‘url’)

Наш рецепт готов! Теперь включаем режим “Add column by fetching URLs”

Окно команды “Add column by fetching URLs”

Две команды соединяются простым символом сложения. Я не нашел у яндекса лимита на количество запросов в секунду, но предполагаю что нам будет достаточно и одного запроса/с, чтобы быть уверенным, что нам не закроют доступ к сервису. Для указания скорости в верхнем правом углу окна есть поле “Throttle delay”, где я указал 1000 ms на один запрос. Теперь нам остается нажать “Start” и ждать результатов.

IV. Парсим Json

Как только процесс завершается, мы получаем дополнительную колонку с длинным и непонятным текстом — ответ в формате Json. Наша следующая задача — разобрать Json на отдельные параметры. Чтобы это сделать, необходимо разобраться в структуре ответа — нажмите “edit” в любой ячейке столбца, выделите текст и скопируйте его в любой редактор/визуализатор Json. Я использую для таких случаев этот и этот инструменты (второй — в комбинации с текстовым редактором Sublime text).

На основании структуры файла формируем запрос. Для Яндекс-карт он такой:

value.parseJson()[“response”][“GeoObjectCollection”][“featureMember”][0][“GeoObject”][“Point”][“pos”]

Запрос отправляем через команду New column based on this column:

Парсим Json

В результате мы получаем новый столбец с координатами, при этом широта и долгота разделены пробелом. Чтобы для каждой координаты создать отдельный столбик, используем уже знакому команду Split column into several columns:

Выделяем координаты в отдельные колонки

Собственно, на этом геокодинг и заканчивается — мы получили координаты для каждого адреса. Однако, к сожалению, случается, что координаты бывают неправильными. В следующей части мы рассмотрим, как можно простейшим образом проверить результат.

Результат геокодирования

V. Проверка

Самый очевидный вариант проверки — расставить точки по координатам на карте. здесь есть несколько вариантов решений:

A. отсечение по Scatterplot

Если адресов очень много, а в результатах вы неуверены, иногда бывает полезно посмотреть на Scatterplot. Чтобы его создать, зайдите в Facet>Scatterplot Facet, и выберите график с комбинацией широты и долготы. При серьезных ошибках, например если в некоторых случаях координаты перепутаны (это, правда, невозможно конкретно при геокодировании) ошибка видна невооруженным глазом. Так-же, на scatterplot можно выделить и удалить, или наоборот, выделить в отдельную базу конкретную область на карте.

Визуализация адресов встроенной диаграммой “Scatterplot”

Б. Визуализация сторонним сервисом

Для визуализации может быть использован сторонний сервис. В своей практике я использую два: Fusion tables от google (простой, данные можно загрузить прямо из OR) и CartoDB (позволяет редактировать записи, перемещая точки прямо на карте). Однако перепроверять все координаты — большой труд, который хочется минимизировать.

Визуализация точек сервисом CartoDB.com
(на других данных)

Очевидно, что ошибка случается в первую очередь при сложных и абстрактных запросах, следовательно, в первую очередь стоит проверить именно их. В зоне риска — адреса без указания конкретного дома, например “парк Музеон”.

Но, если конкретный дом указан, он указывается номером, значит мы можем выделить адреса без цифр в названии, и целенаправленно проверить их. Для выделения нам понадобится функция текстового поиска и использование RegEx (регулярного выражения), для их включения нужно поставить галку в соответствующем чекбоксе.

^[^\d()]+$

В зависимости от данных, мы можем придумать и другие фильтры опасных адресов, например по количеству запятых.

После этого у нас есть выбор — мы можем проверять адреса в фасете вручную (копировать широту и долготу в поле поиска maps.yandex.ru), или выделить их для проверки в внешнем сервисе. В этом случае создадим отдельную колонку с идентификатором сложных адресов.

Fusion tables может красить точки по названию в файле, так что давайте для попавших в фасет строчек впишем в ячейки слово “small_red”, для остальных — “small_blue” (все названия можно посмотреть здесь, cтиль точек назначается так.) В свою очередь СartoDB может раскрашивать точки по любому несовпадающему значению (обычный Css-selector):

#my_Set[icons=’small_red’] { marker-fill: #D30027;}

Теперь мы видим подозрительные адреса на карте и можем проверить и поправить координаты, — иногда их стоить изменить из соображений банальной композиции на экране.

VI. Послесловие

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

http://openrefine.org

--

--