Визуализация геоданных с помощью API и инструментов Mapbox

Среди тех, кто использует Jupyter Notebooks (или аналогичные), есть тенденция, которая заставляет меня думать, что человечество приходит к важному осознанию: Карты Google как API - это дорогое удовольствие.

Независимо от того, встроены ли Google Maps как виджет, ориентированный на потребителя, или как часть обычного конвейера данных, один всплеск высокого трафика может оставить предприятия с ценами в сотни тысяч долларов. На самом деле, я с трудом могу вспомнить продукт, в котором этого не было. Вряд ли можно винить поисковую систему; в конце концов, наша склонность игнорировать Условия использования (а также правила оплаты) всегда была основой бизнес-модели Google. Даже в этом случае предприятий достаточно, чтобы закрывать глаза и охотно платить по таким счетам, не исследуя альтернативы.

В частности, у специалистов по анализу данных нет оправдания бездействию, когда дело доходит до поиска лучшей альтернативы. Оказывается, есть , и он дешевле, проще и, возможно, более полнофункциональный, чем аналог Google Maps. Этим продуктом является Mapbox.

Mapbox - это гораздо больше, чем клон Google API. Веб-продукт предлагает множество функций на основе пользовательского интерфейса, которые мы можем использовать для настройки карт, а также для сохранения или простого преобразования необработанных данных в рабочие данные GeoJSON, даже не касаясь API (который, заметьте, есть… с SDK в каждом мыслимый язык). Мы собираемся создать быструю визуализацию карты, включающую некоторые реальные данные, чтобы познакомиться с функциональностью Mapbox, но это только начало. Загрузите статью, и мы увидим, насколько просто включить Mapbox в такие продукты, как Plot.ly Dash или даже Jupyter Notebooks.

X отмечает место

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

В законе Мерфи четко говорится: «Наличные регулируют все вокруг меня, C.R.E.A.M .; Получите деньги, доллар-доллар, вы все ». Учитывая эту реальность, минимальным требованием для Mapbox должна быть модель ценообразования по сравнению с Google.

Уровни ценообразования Mapbox

Сравните это с прозрачной структурой ценообразования Google:

Уровни ценообразования Google API

Похоже, это убедительный аргумент в столбце выигрышей для Mapbox. Если мы будем оставаться в рамках разумного, Mapbox может служить нам совершенно бесплатной услугой.

Разумеется, нам не хватает чего-то, поскольку мы выбираем бесплатные услуги, верно? Как визуализации Mapbox сочетаются с картами Google?

Https://codepen.io/ro-ka/pen/ENoOjz

Простите за мой французский, но, черт возьми, эта карта крутая. Есть еще много примеров, откуда она взялась, но ясно, что Mapbox похитил сердца научный анализ рынка, а Google занимается потребительским и бизнесом рынками.

Маршрут сегодняшнего вечера: создание карт допинга

Чтобы немного поработать с данными, у нас есть несколько пунктов в нашем контрольном списке:

  • Получите набор данных с данными на основе местоположения: в нашем случае маршрутизации нам нужен набор данных с заданным источником и местом назначения для каждой строки.
  • Создайте маршруты объектов direction, запустив наш набор данных через Mapbox API.
  • Создайте стилизованную карту для нашей презентации с помощью редактора стилей Mapbox.
  • Наложите наши данные маршрута на нашу красивую карту.

Шаг 1. Получите бесплатные данные

Теперь, когда мы как следует обговорили Google, давайте воспользуемся Google. Нам нужно будет получить хорошие данные, а в BigQuery есть несколько потрясающих бесплатных наборов данных, с которыми мы можем работать. Я выберу набор данных Нью-Йорка о поездках Citibike, поскольку он предоставляет чистый набор данных, в котором всегда присутствуют начальные и конечные координаты.

Кстати, BigQuery великолепен. Даже если вы лишь немного разбираетесь в SQL, синтаксис BigQuery, по сути, не зависит от вашего первого предположения.

Конечно, для построения карты нам нужны только начальная и конечная точки, но я решил добавить немного больше ради любопытства:

Шаг 2. Создайте сексуальную карту в Mapbox Studio

Mapbox предоставляет превосходный веб-интерфейс с пометкой «студийный», который поможет нам начать работу. Веб-интерфейс «студии» разделен на три части: настраиваемые стили карты, наборы элементов изображения и наборы данных.

Эти три раздела можно резюмировать следующим образом:

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

Вот краткий обзор редактора стилей карты:

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

Шаг 4. Запустите приложение Flask

Конечно, мы делаем приложение Flask; есть еще какой-нибудь другой? Мы будем использовать настройку Flask Application Factory, как обычно, поэтому в итоге у нас должна получиться файловая структура, как показано ниже. Если вы чувствуете, что забегаете вперед, ознакомьтесь с нашим постом о структурировании приложений Flask.

mapbox-app 
├── /application 
│ └── __init__.py 
├── /datasets 
│ ├── data.json 
│ └── output.csv 
├── /maps │ 
├── __init__.py 
│ ├── /templates 
│ │ └── index.html 
│ ├── views.py 
│ └── plots.py 
├── start.sh 
├── settings.py 
├── wsgi.py 
├── Pipfile 
├── README.md 
└── requirements.txt

Чтобы немного запутаться, на этот раз мы воспользуемся сценарием оболочки для обработки envars и запуска нашего сценария. Начните с создания start.sh:

# start.sh 
export FLASK_APP=wsgi.py 
export FLASK_DEBUG=1 export 
APP_CONFIG_FILE=settings.py 
flask run

Да, для внесения изменений мы будем использовать settings.py в качестве файла конфигурации. Ааа, прямо как во времена Джанго. Этот файл должен содержать токен доступа Mapbox. Mapbox предоставляет вам общедоступный токен по умолчанию во многих своих руководствах (отмечен префиксом pk для 'public key' - - сравните это с sk для "секретный ключ"). Если вы хотите сделать что-нибудь значимое с Mapbox, вам нужно будет получить секретный ключ через пользовательский интерфейс. Затем мы можем добавить этот токен в settings.py как таковой:

MAPBOX_ACCESS_TOKEN="sk.eyJ1IB&F^&f^R&DFRUYFTRUctyTYRUFrtCFTYDYTuEg"

Наконец, взглянем на application/__init__.py, чтобы убедиться, что мы на одной странице:

# application/__init__.py 
import os 
from flask import Flask, g 
def create_app(): 
    """Construct the core application.""" 
    app = Flask(__name__) 
    app.config.from_envvar('APP_CONFIG_FILE', silent=True) 
    with app.app_context(): 
        # Construct map blueprint from maps import mapviews    
        app.register_blueprint(mapviews.map_blueprint) 
        return app

Шаг 5: Создайте план для своей карты

Возможно, вы заметили, что мы зарегистрировали этот Blueprint на предыдущем шаге. Создайте каталог /maps, который мы установим как модуль; нам понадобится это для обработки представления, модели (или только данных) и контроллера (routes.py, как показано ниже).

routes.py

import os
from flask import Blueprint, render_template, request
from flask import current_app as app
from . import locations
map_blueprint = Blueprint('map', __name__, template_folder='templates', static_folder='static')
plot_locations = locations.LocationData()
# Landing Page
@map_blueprint.route('/', methods=['GET'])
def map():
    return render_template('index.html', ACCESS_KEY=app.MAPBOX_ACCESS_KEY,  locations=plot_locations.get_plots, title="CitiBike Mapbox App.")

шаблоны / index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset='utf-8' />
  <title>{{title}}</title>
  <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
  <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.49.0/mapbox-gl.js'></script>
  <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.49.0/mapbox-gl.css' rel='stylesheet' />
  <style>
    body { margin:0; padding:0; }
    #map { position:absolute; top:0; bottom:0; width:100%; }
  </style>
</head>
<body>
<div id='map'></div>
<script>
mapboxgl.accessToken = {{MAPBOX_ACCESS_TOKEN}};
const map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/toddbirchardwework/cjpij1oxl3hiy2spetf5w998w',
  center: [-73.981856, 40.703820],
  zoom: 11.1,
});
map.on('load', function(e) {
  // Add the data to your map as a layer
  map.addLayer({
    id: 'locations',
    type: 'symbol',
    // Add a GeoJSON source containing place coordinates and information.
    source: {
      type: 'geojson',
      data: {{locations}}
    },
    layout: {
      'icon-image': 'restaurant-15',
      'icon-allow-overlap': true,
    }
  });
});
</script>
</body>
</html>

data.py

Обычно именно здесь мы используем магию API Mapbox для получения координат, объектов маршрута или всего, что вы мечтаете построить. Это будет вводный пост, поэтому давайте разберемся с этой логикой в ​​другой раз и воспользуемся набором данных, который Mapbox будет рад получить ради результатов.

Шаг 6. Загрузка нашего набора данных через Mapbox Studio.

Mapbox любезно позволяет нам загружать наши данные через их пользовательский интерфейс Studio, что делает немыслимое; сразу после загрузки Mapbox возьмет данные, которые мы ему предоставим (будь то CSV, GeoJSON и т. д.), и немедленно проанализирует их так, чтобы это имело смысл. Загрузите свой набор данных на https://www.mapbox.com/studio/datasets/:

Затем Mapbox показывает нам предварительный просмотр наших данных еще до того, как мы узнаем, что произошло:

Шаг 7. Сделайте это во Flask

После загрузки набора данных через mapbox studio вы можете фактически повторно загрузить данные с тонким поворотом: ваши данные будут автоматически отформатированы как GeoJSON: формат объектов JSON, которые Mapbox использует для построения точек, рисования маршрутов и т. Д. .

Поскольку у нас был долгий день, я позволю вам загрузить эти предварительно отформатированные данные и зафиксировать значения в представлении карты. Пока у вас все получается легко, но в следующий раз мы будем делать это программно;).

<!DOCTYPE html>
<html>
<head>
  <meta charset='utf-8' />
  <title>{{title}}</title>
  <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
  <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.49.0/mapbox-gl.js'></script>
  <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.49.0/mapbox-gl.css' rel='stylesheet' />
  <style>
    body {
      margin: 0;
      padding: 0;
    }
#map {
      position: absolute;
      top: 0;
      bottom: 0;
      width: 100%;
    }
  </style>
</head>
<body>
<div id='map'></div>
  <script>
    mapboxgl.accessToken = '{{ACCESS_KEY}}';
    const map = new mapboxgl.Map({
      container: 'map',
      style: 'mapbox://styles/toddbirchardwework/cjpij1oxl3hiy2spetf5w998w',
      center: [-73.981856, 40.703820],
      zoom: 11.1,
});
map.addLayer({
      "id": "points",
      "type": "symbol",
      "source": {
        "features": [{
            "type": "Feature",
            "properties": {
              "start_station_name": "Central Park West & W 76 St",
              "end_station_name": "Central Park S & 6 Ave",
              "end_station_latitude": "40.76590936",
              "end_station_longitude": "-73.97634151"
            },
            "geometry": {
              "coordinates": [
                -73.973747,
                40.778967
              ],
              "type": "Point"
            },
            "id": "000a1f944d4dd786d9e7ed04620af02b"
          },
          {
            "type": "Feature",
            "properties": {
              "start_station_name": "W 64 St & West End Ave",
              "end_station_name": "W 70 St & Amsterdam Ave",
              "end_station_latitude": "40.77748046",
              "end_station_longitude": "-73.98288594"
            },
            "geometry": {
              "coordinates": [
                -73.987537,
                40.774528
              ],
              "type": "Point"
            },
            "id": "01d8c19524f067a3f4712653265e0a49"
          },
          {
            "type": "Feature",
            "properties": {
              "start_station_name": "E 20 St & FDR Drive",
              "end_station_name": "W 13 St & 7 Ave",
              "end_station_latitude": "40.73781509",
              "end_station_longitude": "-73.99994661"
            },
            "geometry": {
              "coordinates": [
                -73.975738,
                40.733142
              ],
              "type": "Point"
            },
            "id": "038ac5403b136e34874a7278f64d4e95"
          },
          {
              \\ --------------------------------------
              (etc etc....)
               \\ --------------------------------------
          },
          {
            "type": "Feature",
            "properties": {
              "start_station_name": "Mercer St & Bleecker St",
              "end_station_name": "1 Ave & E 30 St",
              "end_station_latitude": "40.74144387",
              "end_station_longitude": "-73.97536082"
            },
            "geometry": {
              "coordinates": [
                -73.996621,
                40.727063
              ],
              "type": "Point"
            },
            "id": "ff1daf9aadbf0cd6b788bd76f0a3f333"
          }
        ],
        "type": "FeatureCollection"
      },
      "layout": {
        "icon-image": "{icon}-15",
        "text-field": "{title}",
        "text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"],
        "text-offset": [0, 0.6],
        "text-anchor": "top"
      }
    });
  </script>
</body>
</html>

В Mapbox есть еще много возможностей для изучения. Следите за обновлениями до конца этой серии, поскольку мы исследуем создание программных данных GeoData и создаем интерактивные приложения, чтобы действительно вовлечь пользователей в данные карты, позволяя им управлять ограничениями, такими как время и т. Д.

Первоначально опубликовано на сайте hackersandslackers.com 11 декабря 2018 г.