Existem pelo menos dois bons métodos de clustering para o PostGIS: k -means (via kmeans-postgresql
extensão) ou geometrias de clustering dentro de uma distância limite (PostGIS 2.2)
1) k - significa comkmeans-postgresql
Instalação: Você precisa ter o PostgreSQL 8.4 ou superior em um sistema host POSIX (eu não saberia por onde começar para o MS Windows). Se você tiver este instalado a partir de pacotes, verifique também se possui os pacotes de desenvolvimento (por exemplo, postgresql-devel
para o CentOS). Faça o download e extraia:
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/
Antes de compilar, você precisa definir a USE_PGXS
variável de ambiente (minha postagem anterior foi instruída para excluir essa parte do arquivo Makefile
, o que não era a melhor das opções). Um desses dois comandos deve funcionar no seu shell Unix:
# bash
export USE_PGXS=1
# csh
setenv USE_PGXS 1
Agora crie e instale a extensão:
make
make install
psql -f /usr/share/pgsql/contrib/kmeans.sql -U postgres -D postgis
(Nota: Eu também tentei isso com o Ubuntu 10.10, mas sem sorte, pois o caminho pg_config --pgxs
não existe! Esse provavelmente é um bug de empacotamento do Ubuntu)
Uso / Exemplo: Você deve ter uma tabela de pontos em algum lugar (desenhei vários pontos pseudo-aleatórios no QGIS). Aqui está um exemplo com o que eu fiz:
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;
o 5
I fornecido no segundo argumento da kmeans
função window é o número K para produzir cinco clusters. Você pode alterar isso para o número inteiro que desejar.
Abaixo estão os 31 pontos pseudo-aleatórios que desenhei e os cinco centróides com o rótulo mostrando a contagem em cada cluster. Isso foi criado usando a consulta SQL acima.
Você também pode tentar ilustrar onde esses clusters estão com 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) Clustering dentro de uma distância limite com ST_ClusterWithin
Esta função agregada está incluída no PostGIS 2.2 e retorna uma matriz de GeometryCollections onde todos os componentes estão a uma distância um do outro.
Aqui está um exemplo de uso, em que uma distância de 100,0 é o limite que resulta em 5 clusters diferentes:
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;
O maior aglomerado intermediário possui um raio de círculo fechado de 65,3 unidades ou cerca de 130, que é maior que o limite. Isso ocorre porque as distâncias individuais entre as geometrias dos membros são inferiores ao limite e, portanto, as unem como um cluster maior.