В предыдущем разделе мы рассмотрели, как определять пространственные отношения между объектами с помощью предикатов. Теперь перейдём к инструменту, в котором взаимное расположение объектов играет ключевую роль — объединению данных из разных слоёв на основе этих отношений.
Пространственное объединение (spatial join) — это метод, позволяющий связать атрибутивную информацию двух наборов геоданных в зависимости от их взаимного пространственного расположения.
С помощью пространственного объединения можно, например:
определить, к какому району относится каждая точка;
агрегировать данные по пространственным единицам.
В GeoPandas для выполнения таких операций используется функция sjoin, которая позволяет гибко задавать тип пространственного отношения и способ объединения данных.
В этом разделе мы разберём, как выполнять пространственные объединения и применять их для анализа геоданных.
0. Импортируем библиотеки и подготавливаем данные¶
0.1 Импорт библиотек¶
import pandas as pd
import geopandas as gpd0.2 Подготовка данных¶
В этом разделе будут использованы файлы из нашего репозитория:
spb_admin.gpkg — полигональные данные о границах районов и округов Санкт-Петербурга.
Источник: материалы курса «Методы пространственного анализа», НИУ ВШЭ (Р. Гончаров)spb_theaters.csv — данные о театрах Санкт-Петербурга.
Источник: Портал открытых данных Санкт-Петербурга
Прочитаем данные о границах округов в Санкт-Петербурге (spb_admin.gpkg)
okrug_gpkg = gpd.read_file("./data/spb_admin.gpkg", layer="okrug")
okrug_gpkg.explore(tiles="cartodbpositron")Прочитаем данные о театрах Санкт-Петербурга из CSV-файла и создадим на их основе GeoDataFrame.
theaters_csv = pd.read_csv('./data/spb_theaters.csv')
theaters_csv= theaters_csv.dropna(subset=['longitude', 'latitude'])
theaters_gpd = gpd.GeoDataFrame(
theaters_csv,
geometry=gpd.points_from_xy(theaters_csv['longitude'], theaters_csv['latitude']),
crs = 4326
)
theaters_gpd.explore(tiles="cartodbpositron")1. Объединение данных¶
Давайте определим, в каком округе Санкт-Петербурга находится каждый из театров. Для этого выполним пространственное объединение слоя театров со слоем округов.
Вспомним, что при пространственном объединении используется один из пространственных предикатов. В данном случае нам нужно определить, внутри какого округа расположен театр, поэтому будем использовать предикат within.
Перед выполнением операции важно убедиться, что оба слоя находятся в одной системе координат. Если системы координат различаются, один из слоёв необходимо предварительно преобразовать.
1.1. Проверяем системы координат¶
Проверим, совпадают ли системы координат:
okrug_gpkg.crs == theaters_gpd.crsTrueВ нашем случае они совпадают, поэтому мы можем продолжить без дальнейшего перепроецирования
1.2. Выполняем пространственное объединение¶
Для каждого театра определяем округ, внутри которого он расположен. Для этого используем метод sjoin, в котором указываем тип пространственного предиката within, а также способ объединения данных (how="left"), чтобы сохранить все объекты из слоя театров.
theaters_in_okrug = gpd.sjoin(
theaters_gpd,
okrug_gpkg,
how="left",
predicate="within"
)В результате пространственного объединения к каждому объекту театра добавляются атрибуты округа, в границах которого он расположен.
Посмотрим на результат. Выведем названия театров и соответствующих им округов, используя поля так, как они заданы в исходных данных: name — для театров и NAME — для округов.
theaters_in_okrug[["name", "NAME"]].head()Теперь у нас есть информация о том, в каком из округов находится каждый театр
2. Агрегирование результатов¶
После выполнения пространственного объединения у нас есть информация о том, в каком округе расположен каждый театр. Теперь на основе этих данных можно выполнить агрегирование и, например, подсчитать количество театров в каждом округе.
Сгруппируем данные по названию округа (NAME) и подсчитаем количество театров в каждом из них. В результате получаем таблицу, где для каждого округа указано число расположенных в нём театров.
theater_counts = (
theaters_in_okrug
.groupby("NAME")
.size()
.reset_index(name="theater_count")
.sort_values("theater_count", ascending=False)
)
theater_counts.head()Таким образом, пространственное объединение позволяет перейти от анализа отдельных объектов к анализу пространственных единиц.
Итог¶
В этом разделе мы познакомились с пространственным объединением (spatial join) — методом, позволяющим связывать данные разных слоёв на основе их пространственного расположения.
Мы рассмотрели, как с помощью функции sjoin можно сопоставлять объекты из разных слоёв на основе их пространственного расположения.
Также мы увидели, что результат пространственного объединения можно использовать для дальнейшего анализа — например, агрегирования данных и подсчёта количества объектов в пределах заданных территорий.