Existen al menos dos buenos métodos de agrupación para PostGIS: k- medias (a través de la kmeans-postgresql
extensión) o geometrías de agrupación dentro de una distancia umbral (PostGIS 2.2)
1) k- significa conkmeans-postgresql
Instalación: debe tener PostgreSQL 8.4 o superior en un sistema host POSIX (no sabría dónde comenzar para MS Windows). Si tiene esto instalado desde paquetes, asegúrese de tener también los paquetes de desarrollo (por ejemplo, postgresql-devel
para CentOS). Descargar y extraer:
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, debe establecer la USE_PGXS
variable de entorno (mi publicación anterior me indicó que eliminara esta parte de Makefile
, que no era la mejor de las opciones). Uno de estos dos comandos debería funcionar para su shell de Unix:
# bash
export USE_PGXS=1
# csh
setenv USE_PGXS 1
Ahora compila e instala la extensión:
make
make install
psql -f /usr/share/pgsql/contrib/kmeans.sql -U postgres -D postgis
(Nota: ¡también probé esto con Ubuntu 10.10, pero no tuve suerte, ya que la ruta pg_config --pgxs
no existe! Probablemente sea un error de empaquetado de Ubuntu)
Uso / Ejemplo: debe tener una tabla de puntos en alguna parte (dibujé un montón de puntos pseudoaleatorios en QGIS). Aquí hay un ejemplo con lo que hice:
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;
El 5
que proporcioné en el segundo argumento de la kmeans
función de ventana es el entero K para producir cinco grupos. Puede cambiar esto a cualquier número entero que desee.
A continuación se muestran los 31 puntos seudoaleatorios que dibujé y los cinco centroides con la etiqueta que muestra el conteo en cada grupo. Esto fue creado usando la consulta SQL anterior.
También puede intentar ilustrar dónde están estos grupos con 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) Agrupación dentro de una distancia umbral con ST_ClusterWithin
Esta función agregada se incluye con PostGIS 2.2 y devuelve una matriz de GeometryCollections donde todos los componentes están a una distancia entre sí.
Aquí hay un ejemplo de uso, donde una distancia de 100.0 es el umbral que da como resultado 5 grupos 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;
El grupo central más grande tiene un radio de círculo envolvente de 65.3 unidades o aproximadamente 130, que es más grande que el umbral. Esto se debe a que las distancias individuales entre las geometrías de los miembros son menores que el umbral, por lo que lo une como un grupo más grande.