VI. Веб-карта с Folium#
Folium — это библиотека Python для создания интерактивных веб-карт на основе Leaflet.js. С её помощью можно легко визуализировать геопространственные данные, добавлять маркеры, всплывающие подсказки, хлороплетные карты, а также расширять функциональность с помощью плагинов.
Основные возможности Folium:
Создание интерактивных карт с набором нескольких слоев
Добавление маркеров, кружков, всплывающих подсказок и кластеров
Построение картограмм (Choropleth)
Подключение плагинов (MiniMap, MarkerCluster, HeatMap и др.)
В это разделе мы создадим интерактивную карту театров Санкт-Петербурга
Импортируем библиотеки
import folium
import geopandas as gpd
0. Подготовка данных#
Читаем данные
theaters = gpd.read_file('data/spb_theaters.geojson')
admin_district = gpd.read_file('data/spb_admin.gpkg', layer="okrug")
Посчитаем кол-во театров по районам города
# приведем данные в одну систему координат
if theaters.crs != admin_district.crs:
theaters = theaters.to_crs(admin_district.crs)
# Пространственное пересечение
theaters_within_district = gpd.sjoin(theaters, admin_district, how="left", predicate="within")
# Группировка и подсчёт
theaters_count = theaters_within_district.groupby('NAME').size().reset_index(name='theaters_count')
# Соединяем данные со слоем с районами по полю NAME
admin_district_with_count = admin_district.merge(
theaters_count,
on='NAME',
how='left'
)
# Посчитаем кол-во театров на 100 000 ччеловек
admin_district_with_count['theatersPerPop'] = admin_district_with_count['theaters_count']/(admin_district_with_count['Popul']/100000)
# Поcмотрим на данные
admin_district_with_count.head()
NAME | Popul | geometry | theaters_count | theatersPerPop | |
---|---|---|---|---|---|
0 | округ Пискарёвка | 61706.0 | MULTIPOLYGON (((30.35925 59.99390, 30.37635 59... | 1.0 | 1.620588 |
1 | Смолячково | 742.0 | MULTIPOLYGON (((29.42981 60.18954, 29.45195 60... | NaN | NaN |
2 | Молодёжное | 1685.0 | MULTIPOLYGON (((29.45195 60.20537, 29.45554 60... | NaN | NaN |
3 | Серово | 272.0 | MULTIPOLYGON (((29.48220 60.22101, 29.48917 60... | NaN | NaN |
4 | Кронштадт | 44374.0 | MULTIPOLYGON (((29.63402 60.03155, 29.63406 60... | NaN | NaN |
1. Настройка карты#
Внимательно рассмотрите функцию, попробуйте понять, за что отвечает каждая переменная
data = admin_district_with_count.to_crs('EPSG:4326')
m = folium.Map(location=[data.centroid.y.mean(), data.centroid.x.mean()], zoom_start=10, tiles="cartodb positron", control_scale=True)
/var/folders/ry/9bb7wrz54vq_kn2ytlj6ynzm0000gn/T/ipykernel_60143/2365336728.py:2: UserWarning: Geometry is in a geographic CRS. Results from 'centroid' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.
m = folium.Map(location=[data.centroid.y.mean(), data.centroid.x.mean()], zoom_start=10, tiles="cartodb positron", control_scale=True)
Изучите область карты. Понадобятся ли изменения?
m
2. Добавление картограммы#
folium.Choropleth(
name='Theaters Choropleth',
geo_data=admin_district_with_count,
data=admin_district_with_count,
columns=['NAME', 'theatersPerPop'],
fill_color='YlGnBu',
fill_opacity = 0.5,
key_on='feature.properties.NAME',
nan_fill_color='lightgray',
nan_fill_opacity=0.4,
line_color = "white",
legend_name="Theaters per 100 000 "
).add_to(m)
<folium.features.Choropleth at 0x15652b910>
Посмотрим на карту
m
3. Добавление подсказки (tooltip)#
folium.GeoJson(
admin_district_with_count,
name="Districts with tooltips",
style_function=lambda x: {
'fillColor': 'transparent',
'color': 'transparent',
'weight': 0
},
tooltip=folium.GeoJsonTooltip(
fields=['NAME', 'theaters_count'],
aliases=['Округ:', 'Количество театров:'],
localize=True
)
).add_to(m)
<folium.features.GeoJson at 0x15652abf0>
m
Посмотрим на карту
4. Добавление точек в виде маркеров и их кластеризация#
Импортируем плагин
from folium.plugins import MarkerCluster, FeatureGroupSubGroup
Добавляем маркеры и возможность их кластеризации
theaters = theaters[~(theaters.geometry.isna() | theaters.is_empty)]
# Создаём MarkerCluster и SubGroup
marker_cluster = MarkerCluster(name='Theaters').add_to(m)
mc1 = FeatureGroupSubGroup(marker_cluster, 'Theaters').add_to(m)
# Добавляем каждый театр как Marker
for idx, row in theaters.iterrows():
# Координаты
lat = row.geometry.y
lon = row.geometry.x
# Пример popup: имя театра + адрес
popup_text = row['name']
# Tooltip при наведении (можно упростить)
tooltip_text = row['name']
# Маркер с кастомной иконкой
folium.Marker(
location=[lat, lon],
popup=popup_text,
tooltip=tooltip_text,
icon=folium.Icon(icon='heart', prefix='glyphicon', color='darkblue')
).add_to(mc1)
Посмотрим на карту
m
5. Добавление плагинов/виджетов#
Импортируем плагины
from folium.plugins import MousePosition
from folium.plugins import Fullscreen
Добавляем контроль слоёв
folium.LayerControl().add_to(m)
<folium.map.LayerControl at 0x164238400>
Добавлеям координаты курсора
MousePosition().add_to(m)
<folium.plugins.mouse_position.MousePosition at 0x164239fc0>
Добавлеям полноэкранный режим
Fullscreen(
position="bottomright",
title="Expand me",
title_cancel="Exit me",
force_separate_button=True,
).add_to(m)
<folium.plugins.fullscreen.Fullscreen at 0x16423ab00>
Смотрим на карту
m
6. Сохраняем результат#
m.save("index.html")