Существует как минимум два хороших метода кластеризации для PostGIS: k-средства (через kmeans-postgresql
расширение) или кластеризация геометрии в пределах порогового расстояния (PostGIS 2.2)
1) k -значит сkmeans-postgresql
Установка: Вам нужно иметь PostgreSQL 8.4 или выше на хост-системе POSIX (я не знаю, с чего начать для MS Windows). Если вы установили это из пакетов, убедитесь, что у вас также есть пакеты разработки (например, postgresql-devel
для CentOS). Скачать и извлечь:
wget http://api.pgxn.org/dist/kmeans/1.1.0/kmeans-1.1.0.zip
unzip kmeans-1.1.0.zip
cd kmeans-1.1.0/
Перед сборкой необходимо установить USE_PGXS
переменную окружения (мой предыдущий пост проинструктировал удалить эту часть Makefile
, что было не лучшим вариантом). Одна из этих двух команд должна работать для вашей оболочки Unix:
# bash
export USE_PGXS=1
# csh
setenv USE_PGXS 1
Теперь соберите и установите расширение:
make
make install
psql -f /usr/share/pgsql/contrib/kmeans.sql -U postgres -D postgis
(Примечание: я тоже пробовал это с Ubuntu 10.10, но не повезло, так как путь к нему pg_config --pgxs
не существует! Это, вероятно, ошибка упаковки Ubuntu)
Использование / Пример: у вас должна быть где-то таблица точек (я нарисовал кучу псевдослучайных точек в QGIS). Вот пример того, что я сделал:
SELECT kmeans, count(*), ST_Centroid(ST_Collect(geom)) AS geom
FROM (
SELECT kmeans(ARRAY[ST_X(geom), ST_Y(geom)], 5) OVER (), geom
FROM rand_point
) AS ksub
GROUP BY kmeans
ORDER BY kmeans;
5
я обеспечил во втором аргументе kmeans
функции окна является К целому числу , чтобы произвести пять кластеров. Вы можете изменить это на любое целое число, которое вы хотите.
Ниже приведены 31 псевдослучайная точка, которую я нарисовал, и пять центроидов с меткой, показывающей счет в каждом кластере. Это было создано с использованием вышеуказанного SQL-запроса.
Вы также можете попытаться проиллюстрировать, где находятся эти кластеры, с помощью ST_MinimumBoundingCircle :
SELECT kmeans, ST_MinimumBoundingCircle(ST_Collect(geom)) AS circle
FROM (
SELECT kmeans(ARRAY[ST_X(geom), ST_Y(geom)], 5) OVER (), geom
FROM rand_point
) AS ksub
GROUP BY kmeans
ORDER BY kmeans;
2) Кластеризация в пределах порогового расстояния с ST_ClusterWithin
Эта агрегатная функция включена в PostGIS 2.2 и возвращает массив GeometryCollections, где все компоненты находятся на расстоянии друг от друга.
Вот пример использования, где расстояние 100,0 является порогом, который приводит к 5 различным кластерам:
SELECT row_number() over () AS id,
ST_NumGeometries(gc),
gc AS geom_collection,
ST_Centroid(gc) AS centroid,
ST_MinimumBoundingCircle(gc) AS circle,
sqrt(ST_Area(ST_MinimumBoundingCircle(gc)) / pi()) AS radius
FROM (
SELECT unnest(ST_ClusterWithin(geom, 100)) gc
FROM rand_point
) f;
Самый большой средний кластер имеет радиус окружающего круга 65,3 единиц или около 130, что больше, чем пороговое значение. Это связано с тем, что отдельные расстояния между геометриями элементов меньше порога, поэтому он связывает их вместе как один более крупный кластер.