22 марта 2021

🗺 Работа с геоданными в Python и Jupyter

Пишу об IT и на Python. kungurov.net
Строим карту бесплатных точек доступа Wi-Fi в Москве, прокладываем маршрут московского марафона, создаем интерактивную карту регионов РФ и хороплет-карту штатов США по COVID-19 с помощью блокнотов Jupyter, библиотек pandas, gmaps, ipyleaflet и folium.
🗺 Работа с геоданными в Python и Jupyter

Рассмотрим три библиотеки по работе с геоданными: gmaps, ipyleaflet и более продвинутую по сравнению с предыдущими – folium. Забегая вперед, скажем, что лучше использовать folium, так как в ней удобнее строить интерактивные карты и работать со слоями. В конце статьи вы найдете ссылки на блокноты с кодом.

Установка Jupyter

Установим блокноты Jupyter следующей командой:

        pip install notebook
    

Запустим блокноты Jupyter:

        jupyter notebook
    

Автоматически откроется страница по адресу http://localhost:8888/tree. Затем создадим новый блокнот, кликнув по кнопке New.

1. Библиотека gmaps

Начнем с простого – библиотеки gmaps. Для работы с ней нужен API-ключ. Как его получить читайте на сайте Google Maps Platform.

Помимо gmaps нам понадобятся инструменты интерактивного управления ipywidgets, widgetsnbextension и библиотека для обработки и анализа данных pandas. Они устанавливаются как через консоль (pip install), так и прямо из блокнота через восклицательный знак (!pip install):

        !pip install gmaps
!pip install pandas
!pip install widgetsnbextension
    

Активируем виджеты следующими командами:

        !jupyter nbextension enable --py --sys-prefix widgetsnbextension
!jupyter nbextension enable --py --sys-prefix gmaps
    

1.1. Карта точек WiFi

Рис. 1. Карта с маркерами точек WiFi (gmaps)
Рис. 1. Карта с маркерами точек WiFi (gmaps)

За основу возьмем датасет, размещенный на портале открытых данных Москвы, в котором содержится информация о 2.8 тыс. бесплатных точек Wi-Fi. На каждой 1001-й строчке датасета дублируются названия столбцов. Во избежание ошибок при обработке набора данных, удалим эти строчки из таблицы. Очищенный массив доступен в репозитории на Гитхабе.

Какую информацию возьмем из датасета? Нам нужны координаты (Latitude_WGS84, Longitude_WGS84), адрес (Location) и количество точек доступа (NumberOfAccessPoints).

Cоздадим список wifi_points, состоящий из словарей, в каждом из которых хранится вышеперечисленная информация о каждой точке. Затем создадим отдельный список marker_coordinates с координатами и переведем элементы списка из типа строка str в тип вещественное число float, потому что координаты – это число, а не строчка.

wifi_gmaps.ipynb
        import pandas as pd
import gmaps

file_name = 'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/data-9776-2020-12-21.csv'
df = pd.read_csv(file_name, sep=';', encoding='cp1251')

gmaps.configure(api_key='...')

wifi_points = []
i = 0
while i < len(df.index):
    wifi_points.append({'Coordinates': [df['Latitude_WGS84'][i], df['Longitude_WGS84'][i]], 'Location': df['Location'][i], 'NumberOfAccessPoints': df['NumberOfAccessPoints'][i]})
    i += 1

marker_coordinates = [wifi['Coordinates'] for wifi in wifi_points]
marker_coordinates = [[float(x) for x in y] for y in marker_coordinates] # здесь мы проходимся по элементами вложенных списков и меняем их типы со str на float

info_box_template = """
<dl>
<dt>Адрес:</dt><dd>{Location}</dd>
<dt>Количество точек доступа:</dt><dd>{NumberOfAccessPoints}</dd>
</dl>
"""

marker_info  = [info_box_template.format(**points) for points in wifi_points]
marker_layer = gmaps.marker_layer(marker_coordinates, info_box_content=marker_info )

fig = gmaps.figure()
fig.add_layer(marker_layer)
fig
    

Здесь:

sep – разделитель между столбцами.
encoding – кодировка файла.

info_box_template – формирует HTML-форму с описанием точки Wi-Fi.
<dl> – создает контейнер.
<dt> – заголовок.
<dd> – описание.

marker_info – список, содержащий форматированные строчки с описанием точек Wi-Fi: адрес точки (Location) и количество работающих точек Wi-Fi (NumberOfAccessPoints).

marker_layer – создает слой маркеров с соответствующими координатами.
fig = gmaps.figure() – инициирует создание карты.
fig.add_layer(marker_layer) – добавляет слой с маркерами на карту.
fig – запускает карту.

Ошибка Figure(layout)
Если при запуске блокнота выскочила ошибка Figure(layout=FigureLayout(height='420px')), то перезапустите блокнот, но не через панель управления блокнотом (KernelRestart), а через консоль.

2. Библиотека ipyleaflet

ipyleaflet – интерактивная библиотека виджетов, основанная ipywidgets. Библиотека использует карты OpenStreetMap.

Установим библиотеки pandas, ipyleaflet и ipywidgets:

        !pip install pandas
!pip install ipyleaflet
!pip install ipywidgets
    

2.1. Карта точек WiFi

Рис. 2. Карта с маркерами точек WiFi (ipyleaflet)
Рис. 2. Карта с маркерами точек WiFi (ipyleaflet)

Создадим карту с точками Wi-Fi, но уже с помощью библиотеки ipyleaflet. Воспользуемся датасетом из раздела про gmaps:

        import pandas as pd
from ipywidgets import HTML
from ipyleaflet import Map, Marker, Popup

file_name = 'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/data-9776-2020-12-21.csv'
df = pd.read_csv(file_name, sep=';', encoding='cp1251')

wifi_points = []
i = 0
while i < len(df.index):
    wifi_points.append({'index': i, 'Coordinates': [df['Latitude_WGS84'][i], df['Longitude_WGS84'][i]], 'Location': df['Location'][i], 'NumberOfAccessPoints': df['NumberOfAccessPoints'][i]})
    i += 1

marker_coordinates = [wifi['Coordinates'] for wifi in wifi_points]
marker_coordinates = [[float(x) for x in y] for y in marker_coordinates]

m = Map(center=(55.753215, 37.622504), zoom=11)

markers = [Marker(location=(marker_coordinates[i])) for i in range(len(marker_coordinates))]

info_box_template = """
<dl>
<dt>Адрес:</dt><dd>{Location}</dd>
<dt>Количество точек доступа:</dt><dd>{NumberOfAccessPoints}</dd>
</dl>
"""

locations_info  = [info_box_template.format(**point) for point in wifi_points]

for i in range(len(markers)):
    markers[i].popup = HTML(locations_info[i])
    m.add_layer(markers[i])

m
    

Здесь:

markers – список из координат маркеров.

locations_info – список из адресов и количества точек Wi-Fi.

for i in range(len(markers)) – каждый из элементов на карте представляет из себя слой, поэтому напишем цикл создающий нужное количество слоев. Один слой – один маркер.

m – отрисовывает карту с маркерами.

Ошибка: виджеты не отображаются
Если виджеты не отображаются, перезапустите блокноты Jupyter через консоль.

2.2. Маршрут марафона

Рис. 3. Маршрут 5 км московского марафона (ipyleaflet)
Рис. 3. Маршрут 5 км московского марафона (ipyleaflet)

Построим маршрут 5 км московского марафона: импортируем из библиотеки ipyleaflet модуль «Муравьиный путь» AntPath и добавим маркеры Старт и Финиш!.

        from ipyleaflet import AntPath, WidgetControl
from ipywidgets import IntSlider, jslink

m = Map(center=(55.718148, 37.555493), zoom=13)

marathon_path = AntPath(
    locations=[
        [55.717435, 37.561014], [55.712517, 37.569324], [55.712412, 37.569479],
        [55.711333, 37.561858], [55.711344, 37.558516], [55.712049, 37.553513],
        [55.713216, 37.550191], [55.71523, 37.54681], [55.717366, 37.544289],
        [55.719874, 37.542966], [55.721958, 37.542939], [55.723928, 37.543701], 
        [55.725656, 37.545167], [55.7267, 37.546673], [55.727594, 37.54923], 
        [55.727481, 37.549349], [55.727053, 37.547923], [55.726619, 37.546807], 
        [55.724107, 37.549236], [55.723902, 37.549511], [55.720267, 37.5558]
    ],
    dash_array=[1, 10],
    delay=1000,
    color='#9500ff',
    pulse_color='#9500ff'
)

m.add_layer(marathon_path)

start_marker = Marker(location=(55.717435, 37.561014))
m.add_layer(start_marker)

finish_marker = Marker(location=(55.720267, 37.5558))
m.add_layer(finish_marker)

start = HTML()
finish = HTML()
start.value = "Старт"                                                                      
finish.value = "Финиш!"                                                                      
start_marker.popup = start
finish_marker.popup = finish

zoom_slider = IntSlider(description='Масштаб:', min=11, max=15, value=14)
jslink((zoom_slider, 'value'), (m, 'zoom'))
widget_control1 = WidgetControl(widget=zoom_slider, position='topright')
m.add_control(widget_control1)

m
    

Здесь:

marathon_path – координаты марафона.

start_marker и finish_marker – координаты маркеров Старт и Финиш! соответственно.

start.value и finish.value – описания маркеров старта и финиша, которые появятся во всплывающем окне при клике на маркер.

zoom_slider – ползунок масштаба.

color – цвет линии.

pulse_color – цвет бегущих муравьев.

2.3. Маршрут марафона с иконками AwesomeIcon

Рис. 4. Маршрут марафона с иконками AwesomeIcon (ipyleaflet)
Рис. 4. Маршрут марафона с иконками AwesomeIcon (ipyleaflet)

Заменим стандартные иконки маркеров на иконки из каталога AwesomeIcon:

        from ipyleaflet import AwesomeIcon

m = Map(center=(55.718148, 37.555493), zoom=14)

marathon_path = AntPath(
    locations=[
        [55.717435, 37.561014], [55.712517, 37.569324], [55.712412, 37.569479],
        [55.711333, 37.561858], [55.711344, 37.558516], [55.712049, 37.553513],
        [55.713216, 37.550191], [55.71523, 37.54681], [55.717366, 37.544289],
        [55.719874, 37.542966], [55.721958, 37.542939], [55.723928, 37.543701], 
        [55.725656, 37.545167], [55.7267, 37.546673], [55.727594, 37.54923], 
        [55.727481, 37.549349], [55.727053, 37.547923], [55.726619, 37.546807], 
        [55.724107, 37.549236], [55.723902, 37.549511], [55.720267, 37.5558]
    ],
    dash_array=[1, 10],
    delay=1000,
    color='#9500ff',
    pulse_color='#9500ff'
)

m.add_layer(marathon_path)

start_icon = AwesomeIcon(
    name='fa-play',
    marker_color='green',
    icon_color='white'
)

start_marker = Marker(icon=start_icon, location=(55.717435, 37.561014))
start = HTML()
start.value = "Старт"   
start_marker.popup = start
m.add_layer(start_marker)

finish_icon = AwesomeIcon(
    name='fa-stop',
    marker_color='blue',
    icon_color='black'
)

finish_marker = Marker(icon=finish_icon, location=(55.720267, 37.5558))
finish = HTML()                                                                 
finish.value = "Финиш!"                                                                      
finish_marker.popup = finish
m.add_layer(finish_marker)

zoom_slider = IntSlider(description='Масштаб:', min=11, max=17, value=14)
jslink((zoom_slider, 'value'), (m, 'zoom'))
widget_control1 = WidgetControl(widget=zoom_slider, position='topright')
m.add_control(widget_control1)

m
    

Здесь:

start_icon и finish_icon – содержат элементы из библиотеки AwesomeIcon.

marker_color – цвет маркера.

icon_color – цвет иконки.

2.4. Маршрут марафона с собственными иконками

Рис. 5. Маршрут марафона с собственными иконками (ipyleaflet)
Рис. 5. Маршрут марафона с собственными иконками (ipyleaflet)

Добавим собственные иконки с помощью модуля Icon:

        from ipyleaflet import Icon
from ipywidgets import IntSlider

m = Map(center=(55.718148, 37.555493), zoom=14)

ant_path = AntPath(
    locations=[
        [55.717435, 37.561014], [55.712517, 37.569324], [55.712412, 37.569479],
        [55.711333, 37.561858], [55.711344, 37.558516], [55.712049, 37.553513],
        [55.713216, 37.550191], [55.71523, 37.54681], [55.717366, 37.544289],
        [55.719874, 37.542966], [55.721958, 37.542939], [55.723928, 37.543701], 
        [55.725656, 37.545167], [55.7267, 37.546673], [55.727594, 37.54923], 
        [55.727481, 37.549349], [55.727053, 37.547923], [55.726619, 37.546807], 
        [55.724107, 37.549236], [55.723902, 37.549511], [55.720267, 37.5558]
    ],
    dash_array=[1, 10],
    delay=1000,
    color='#9500ff',
    pulse_color='#9500ff'
)

m.add_layer(ant_path)

start_icon = Icon(icon_url='https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/5d6126a97905792c584b1f9e18cd8dd767ba2966/start.png', icon_size=[97, 36])
start_marker = Marker(icon=start_icon, location=(55.717435, 37.561014))
start = HTML()
start.value = "Старт"   
start_marker.popup = start
m.add_layer(start_marker)

finish_icon = Icon(icon_url='https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/5d6126a97905792c584b1f9e18cd8dd767ba2966/finish.png', icon_size=[97, 36])

finish_marker = Marker(icon=finish_icon, location=(55.720267, 37.5558))
finish = HTML()                                                                 
finish.value = "Финиш!"                                                                      
finish_marker.popup = finish
m.add_layer(finish_marker)

zoom_slider = IntSlider(description='Масштаб:', min=11, max=17, value=14)
jslink((zoom_slider, 'value'), (m, 'zoom'))
widget_control1 = WidgetControl(widget=zoom_slider, position='topright')
m.add_control(widget_control1)

m
    

Здесь:

Импортируем из библиотеки ipyleaflet модуль Icon, чтобы использовать собственные иконки.

icon_url – ссылка на иконку.

icon_size=[x, y] – задает размеры иконки: x – длина, y – высота.

2.5. Карта 85 субъектов РФ

Рис. 6. Карта 85 субъектов РФ (ipyleaflet)
Рис. 6. Карта 85 субъектов РФ (ipyleaflet)

Создадим карту с 85 субъектами РФ. Координаты границ субъектов возьмем из json-файла. Данные актуальны на 2015 год и в них есть дефект с Чукотским Автономным округом, но для нашей задачи – демонстрации возможностей библиотеки – этого вполне достаточно. Очищенная версия лежит в репозитории.

        import os
import json
import random
import requests
from ipyleaflet import GeoJSON

def load_data(url, filename, file_type):
    r = requests.get(url)
    with open(filename, 'w') as f:
        f.write(r.content.decode("utf-8"))
    with open(filename, 'r') as f:
        return file_type(f)

data = load_data(
    'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/geo_ru.json',
    'geo_ru.json',
     json.load)    

def random_color(feature):
    return {
        'color': 'black',
        'fillColor': random.choice(['red', 'yellow', '#efed69', '#fcba03', '#9900ff', '#00ff15', '#db2751', '#00ff95']),
    }

m = Map(center=(66.25, 94.15), zoom=3)

geo_json = GeoJSON(
    data=data,
    style={
        'opacity': 1, 'dashArray': '9', 'fillOpacity': 0.2, 'weight': 1
    },
    hover_style={
        'color': 'white', 'dashArray': '0', 'fillOpacity': 0.7
    },
    style_callback=random_color
)

m.add_layer(geo_json)

m
    

Здесь:

load_data – функция, которая записывает файл с данным в локальное хранилище.

random_color – функция, генерирующая случайные цвета для субъектов РФ.

style и hover_style – задают графическое отображение субъекта по умолчанию и при наведении на него курсора мыши.

2.6. Интерактивная карта РФ (по клику)

Рис. 7. Интерактивная карта 85 субъектов РФ (ipyleaflet)
Рис. 7. Интерактивная карта 85 субъектов РФ (ipyleaflet)

Сделаем карту интерактивной: при клике на субъект под картой появится название центрального города субъекта:

        def load_data(url, filename, file_type):
    r = requests.get(url)
    with open(filename, 'w') as f:
        f.write(r.content.decode("utf-8"))
    with open(filename, 'r') as f:
        return file_type(f)

data = load_data(
    'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/geo_ru.json',
    'geo_ru.json',
     json.load)    

def random_color(feature):
    return {
        'color': 'black',
        'fillColor': random.choice(['red', 'yellow', '#efed69', '#fcba03', '#9900ff', '#00ff15', '#db2751', '#00ff95']),
    }

m = Map(center=(66.25, 94.15), zoom=3)

geo_json = GeoJSON(
    data=data,
    style={
        'opacity': 1, 'dashArray': '9', 'fillOpacity': 0.2, 'weight': 1
    },
    hover_style={
        'color': 'white', 'dashArray': '0', 'fillOpacity': 0.7
    },
    style_callback=random_color
)

def handle_click(**kwargs):
    print(kwargs['feature']['properties']['name']) 
    
geo_json.on_click(handle_click)
m.add_layer(geo_json)

m
    

Здесь:

handle_click – функция, которая принимает именованные аргументы.

['name'] – имя субъекта.

geo_json.on_click(handle_click) – подключает к карте событие (вывод на экран) при клике на субъект.

2.7. Больше интерактива

Рис. 8. Интерактивная карта 85 субъектов РФ (ipyleaflet)
Рис. 8. Интерактивная карта 85 субъектов РФ (ipyleaflet)

Теперь, с помощью функции handle_hover сделаем так, чтобы название центрального города субъекта появлялось при наведении курсора мыши на субъект:

        def load_data(url, filename, file_type):
    r = requests.get(url)
    with open(filename, 'w') as f:
        f.write(r.content.decode("utf-8"))
    with open(filename, 'r') as f:
        return file_type(f)

data = load_data(
    'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/geo_ru.json',
    'geo_ru.json',
     json.load)    

def random_color(feature):
    return {
        'color': 'black',
        'fillColor': random.choice(['red', 'yellow', '#efed69', '#fcba03', '#9900ff', '#00ff15', '#db2751', '#00ff95']),
    }

m = Map(center=(66.25, 94.15), zoom=3)

geo_json = GeoJSON(
    data=data,
    style={
        'opacity': 1, 'dashArray': '9', 'fillOpacity': 0.2, 'weight': 1
    },
    hover_style={
        'color': 'white', 'dashArray': '0', 'fillOpacity': 0.7
    },
    style_callback=random_color
)

def handle_hover(**kwargs):
    print(kwargs['feature']['properties']['name']) 
    
geo_json.on_hover(handle_hover)
m.add_layer(geo_json)

m
    

Здесь:

handle_hover – функция, принимающая именованные аргументы.

geo_json.on_click(handle_hover) – подключает к карте событие при наведении на субъект.

2.8. Хороплет-карта США по COVID-19

Рис. 9. Хороплет-карта карта США по COVID-19 (ipyleaflet)
Рис. 9. Хороплет-карта карта США по COVID-19 (ipyleaflet)

Построим хороплет-карту (фоновая картограмма) штатов США по COVID-19. На хороплет-карте цветом с различной степенью насыщенности отображается интенсивность какого-либо показателя. Данные по заболеваемости возьмем из репозитория университета Джона Хопкинса, а координаты границ штатов с сайта библиотеки ipyleaflet. Слегка изменим csv-файл, добавив в него второй столбец State с почтовыми сокращениями штатов США (Alabama – AL и так далее), чтобы была связь со вторым ключом (id) для каждого штата из json-файла. Также удалим несколько штатов из csv-файла, границы которых отсутствуют в json-файле.

        import ipyleaflet
from ipywidgets import link, FloatSlider
from branca.colormap import linear

def load_data(url, filename, file_type):
    r = requests.get(url)
    with open(filename, 'w') as f:
        f.write(r.content.decode("utf-8"))
    with open(filename, 'r') as f:
        return file_type(f)

geo_json_data = load_data(
    'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/us-states_covid.json',
    'us-states_covid.json',
     json.load)

confirmed = load_data(
    'https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/03-13-2021_covid.csv',
    '03-13-2021_covid.csv',
     pd.read_csv)

confirmed =  dict(zip(confirmed['State'].tolist(), confirmed['Confirmed'].tolist()))

layer = ipyleaflet.Choropleth(
    geo_data=geo_json_data,
    choro_data=confirmed,
    colormap=linear.YlOrRd_04,
    border_color='black',
    style={'fillOpacity': 0.8, 'dashArray': '5, 5'})

m = ipyleaflet.Map(center = (43,-100), zoom = 4)
m.add_layer(layer)
m
    

Здесь:

geo_json_data – загрузка json-файла с координатами границ штатов.

сonfirmed – загрузка csv-файла с данными по заболеваемости.

confirmed = dict... – создает словарь с ключем Почтовое название штата и значением Количество подтвержденных случаев заражения.

geo_data – координаты границ штатов.

choro_data – хороплет-данные, количество заболевших в каждом штате.

colormap – цвет из палитры ColorBrewer.

3. Библиотека folium

Теперь воспользуемся библиотекой folium, которая также работает на картах OpenStreetMap, но обладает большими возможностями по сравнению с ipyleaflet.

3.1. Установка folium

Установим folium следующей командой:

        !pip install folium
    

3.2. Два слоя на одной карте

Рис. 10. Хороплет-карта США по COVID-19 (folium). Два слоя на одной карте.
Рис. 10. Хороплет-карта США по COVID-19 (folium). Два слоя на одной карте.

Построим карту по COVID-19 в США с двумя слоями: количество заболевших в каждом штате и летальность.

        import folium

url = (
    "https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
)
state_geo = "https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/us-states_covid.json"
covid_csv = "https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/03-13-2021_covid.csv"
state_data = pd.read_csv(covid_csv)

m = folium.Map(location=[48, -102], zoom_start=3)

folium.Choropleth(
    geo_data=state_geo,
    name="Подтвержденные случаи заражения",
    data=state_data,
    columns=["State", "Confirmed"],
    key_on="feature.id",
    fill_color="YlOrBr",
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name="Подтвержденные случаи заражения",
).add_to(m)

print()

folium.Choropleth(
    geo_data=state_geo,
    name="Летальность",
    data=state_data,
    columns=["State", "Case_Fatality_Ratio"],
    key_on="feature.id",
    fill_color="Reds",
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name="Летальность",
    show = False,  
).add_to(m)

folium.LayerControl().add_to(m)

m
    

Здесь:

folium.Choropleth – импорт модуля для построения карты.

columns – столбцы, которые используются для построения карты.

key – ключ, используемый для построения карты. По умолчанию id.

name – название карты.

fill_color – цвет из палитры ColorBrewer. Если данных в столбце нет (NaN), то цвет будет серый.

legend_name – описание под шкалой.

show – определяет, показывать ли слой при загрузке карты. По умолчанию значение True.

Рис. 11. Хороплет-карта США по COVID-19 (folium). Два слоя на одной карте.
Рис. 11. Хороплет-карта США по COVID-19 (folium). Два слоя на одной карте.

3.3. Добавляем интерактив: всплывающий текст

Рис. 12. Интерактивная хороплет-карта США по COVID-19 (folium)
Рис. 12. Интерактивная хороплет-карта США по COVID-19 (folium)

Сделаем так, чтобы при наведении курсора мыши на штат всплывало название штата:

        url = (
    "https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
)
state_geo = "https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/us-states_covid.json"
covid_csv = "https://raw.githubusercontent.com/tttdddnet/Python-Jupyter-Geo/main/03-13-2021_covid.csv"
state_data = pd.read_csv(covid_csv)

m = folium.Map(location=[48, -102], zoom_start=3)

covid_map = folium.Choropleth(
    geo_data=state_geo,
    name="Подтвержденные случаи заражения",
    data=state_data,
    columns=["State", "Confirmed"],
    key_on="feature.id",
    fill_color="YlOrBr",
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name="Подтвержденные случаи заражения",
).add_to(m)

folium.LayerControl().add_to(m)

covid_map.geojson.add_child(folium.features.GeoJsonTooltip(['name',], labels=False))

m
    

Здесь:

covid_map.geojson.add_child... – добавляет всплывающее окошко с названием штата.

3.4. Две карты в одном окне

Рис. 13. Две карты в одном окне (folium).
Рис. 13. Две карты в одном окне (folium).

Создадим две карты в одном окне с помощью плагина DualMap. Для этого добавим к основной карте m дочерние карты m1 и m2 через запись m.m1 и m.m2 соответственно:

        from folium import plugins

m = plugins.DualMap(location=(59.93863, 30.31413), tiles=None, zoom_start=11)

folium.TileLayer("openstreetmap").add_to(m)
folium.TileLayer("Stamen Terrain").add_to(m.m1)
folium.TileLayer("cartodbpositron").add_to(m.m2)


figure_both = folium.FeatureGroup(name="Метка на обеих картах").add_to(m)
figure_1 = folium.FeatureGroup(name="Метка слева").add_to(m.m1)
figure_2 = folium.FeatureGroup(name="Метка справа").add_to(m.m2)

icon_red = folium.Icon(color="green")
folium.Marker((59.93863, 30.31413), tooltip="Метка на обеих картах", icon=icon_red).add_to(figure_both)
folium.Marker((59.912563, 30.32413), tooltip="Метка слева").add_to(figure_1)
folium.Marker((59.93463, 30.38413), tooltip="Метка справа").add_to(figure_2)

folium.LayerControl(collapsed=False).add_to(m)

m
    

Здесь:

folium.TileLayer(" ") – добавляет на карту картографический слой. В нашем случае: openstreetmap, Stamen Terrain и cartodbpositron.

m.m1 и m.m2 – создает две карты: первая карта (слева) и вторая карта (справа).

.add_to(m), .add_to(m.m1), .add_to(m.m2) – добавляют маркеры на обе карты, только на первую карту и только на вторую соответственно.

3.5. Группируем маркеры

Рис. 14. Группируем маркеры в (folium)
Рис. 14. Группируем маркеры в (folium)

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

        m = folium.Map(location=[59.93863, 30.31413], zoom_start=12)

figure = folium.FeatureGroup(name="Все метки")
m.add_child(figure)

group1 = plugins.FeatureGroupSubGroup(figure, "Первая группа")
m.add_child(group1)

group2 = plugins.FeatureGroupSubGroup(figure, "Вторая группа")
m.add_child(group2)

folium.Marker([59.93863, 30.31413]).add_to(group1)
folium.Marker([59.95863, 30.31413]).add_to(group1)

folium.Marker([59.94863, 30.32513]).add_to(group2)
folium.Marker([59.91763, 30.31413]).add_to(group2)

folium.LayerControl(collapsed=False).add_to(m)

m
    

Здесь:

plugins.FeatureGroupSubGroup(figure, "name") – создает группы маркеров с именем name.

m.add_child(group1) – добавляет группы маркеров на карту.

folium.Marker([59.93863, 30.31413]).add_to(group1) – добавляет маркер в группу.

***

Мы проделали большую работу и познакомились с тремя географическими библиотеками: gmaps, ipyleaflet и folium. С их помощью научились:

  • ставить на карту маркеры, группировать их и менять иконки маркеров на собственные;
  • выделять на карте границы субъектов РФ и штатов США;
  • рисовать хороплет-карты;
  • создавать в одном окне две карты;
  • читать json- и csv-файлы.
***

Блокноты

Источники

Читайте также




МЕРОПРИЯТИЯ

Комментарии

ВАКАНСИИ

Добавить вакансию
Senior Java Developer
Москва, по итогам собеседования
Go-разработчик
по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ