These functions implement clustering algorithms for sets of geometries.

# Clustering Functions

ST_ClusterDBSCAN

Window function that returns a cluster id for each input geometry using the DBSCAN algorithm.

    			integer ST_ClusterDBSCAN

    			geometry winset
    			geom

    			float8
    			eps

    			integer
    			minpoints

### Description

Returns cluster number for each input geometry, based on a 2D implementation of the Density-based spatial clustering of applications with noise (DBSCAN) algorithm. Unlike ST_ClusterKMeans, it does not require the number of clusters to be specified, but instead uses the desired distance (`eps`) and density (`minpoints`) parameters to construct each cluster.

An input geometry will be added to a cluster if it is either:

- A "core" geometry, that is within `eps` distance of at least `minpoints` input geometries (including itself) or

- A "border" geometry, that is within `eps` distance of a core geometry.

Note that border geometries may be within `eps` distance of core geometries in more than one cluster; in this case, either assignment would be correct, and the border geometry will be arbitrarily asssigned to one of the available clusters. In these cases, it is possible for a correct cluster to be generated with fewer than `minpoints` geometries. When assignment of a border geometry is ambiguous, repeated calls to ST_ClusterDBSCAN will produce identical results if an ORDER BY clause is included in the window definition, but cluster assignments may differ from other implementations of the same algorithm.

Input geometries that do not meet the criteria to join any other cluster will be assigned a cluster number of NULL.

Availability: 2.3.0

### Examples

Assigning a cluster number to each polygon within 50 meters of each other. Require at least 2 polygons per cluster

within 50 meters at least 2 per cluster. singletons have NULL for cid
    SELECT name, ST_ClusterDBSCAN(geom, eps := 50, minpoints := 2) over () AS cid
    FROM boston_polys
    WHERE name > '' AND building > ''
    	AND ST_DWithin(geom,
            ST_Transform(
                ST_GeomFromText('POINT(-71.04054 42.35141)', 4326), 26986),
               500);
                    name                 | bucket
    -------------------------------------+--------
     Manulife Tower                      |      0
     Park Lane Seaport I                 |      0
     Park Lane Seaport II                |      0
     Renaissance Boston Waterfront Hotel |      0
     Seaport Boston Hotel                |      0
     Seaport Hotel & World Trade Center  |      0
     Waterside Place                     |      0
     World Trade Center East             |      0
     100 Northern Avenue                 |      1
     100 Pier 4                          |      1
     The Institute of Contemporary Art   |      1
     101 Seaport                         |      2
     District Hall                       |      2
     One Marina Park Drive               |      2
     Twenty Two Liberty                  |      2
     Vertex                              |      2
     Vertex                              |      2
     Watermark Seaport                   |      2
     Blue Hills Bank Pavilion            |   NULL
     World Trade Center West             |   NULL
    (20 rows)

Combining parcels with the same cluster number into a single geometry. This uses named argument calling

    SELECT cid, ST_Collect(geom) AS cluster_geom, array_agg(parcel_id) AS ids_in_cluster FROM (
        SELECT parcel_id, ST_ClusterDBSCAN(geom, eps := 0.5, minpoints := 5) over () AS cid, geom
        FROM parcels) sq
    GROUP BY cid;

### See Also

ST_DWithin, ST_ClusterKMeans, ST_ClusterIntersecting, ST_ClusterWithin

ST_ClusterIntersecting

Aggregate function that clusters the input geometries into connected sets.

                geometry[] ST_ClusterIntersecting
                geometry set g

### Description

ST_ClusterIntersecting is an aggregate function that returns an array of GeometryCollections, where each GeometryCollection represents an interconnected set of geometries.

Availability: 2.2.0

### Examples

    WITH testdata AS
      (SELECT unnest(ARRAY['LINESTRING (0 0, 1 1)'::geometry,
    		       'LINESTRING (5 5, 4 4)'::geometry,
    		       'LINESTRING (6 6, 7 7)'::geometry,
    		       'LINESTRING (0 0, -1 -1)'::geometry,
    		       'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))'::geometry]) AS geom)

    SELECT ST_AsText(unnest(ST_ClusterIntersecting(geom))) FROM testdata;

    --result

    st_astext
    ---------
    GEOMETRYCOLLECTION(LINESTRING(0 0,1 1),LINESTRING(5 5,4 4),LINESTRING(0 0,-1 -1),POLYGON((0 0,4 0,4 4,0 4,0 0)))
    GEOMETRYCOLLECTION(LINESTRING(6 6,7 7))

### See Also

ST_ClusterDBSCAN, ST_ClusterKMeans, ST_ClusterWithin

ST_ClusterKMeans

Window function that returns a cluster id for each input geometry using the K-means algorithm.

    			integer ST_ClusterKMeans

    			geometry winset
    			geom

    			integer
    			number_of_clusters

### Description

Returns 2D distance based K-means cluster number for each input geometry. The distance used for clustering is the distance between the centroids of the geometries.

Availability: 2.3.0

### Examples

Generate dummy set of parcels for examples

    CREATE TABLE parcels AS
    SELECT lpad((row_number() over())::text,3,'0') As parcel_id, geom,
    ('{residential, commercial}'::text[])[1 + mod(row_number()OVER(),2)] As type
    FROM
        ST_Subdivide(ST_Buffer('LINESTRING(40 100, 98 100, 100 150, 60 90)'::geometry,
        40, 'endcap=square'),12) As geom;

Original Parcels | Parcels color-coded by cluster number (cid)
    SELECT ST_ClusterKMeans(geom, 5) OVER() AS cid, parcel_id, geom
    FROM parcels;
    -- result
     cid | parcel_id |   geom
    -----+-----------+---------------
       0 | 001       | 0103000000...
       0 | 002       | 0103000000...
       1 | 003       | 0103000000...
       0 | 004       | 0103000000...
       1 | 005       | 0103000000...
       2 | 006       | 0103000000...
       2 | 007       | 0103000000...
    (7 rows)

     -- Partitioning parcel clusters by type
    SELECT ST_ClusterKMeans(geom,3) over (PARTITION BY type) AS cid, parcel_id, type
    FROM parcels;
    -- result
     cid | parcel_id |    type
    -----+-----------+-------------
       1 | 005       | commercial
       1 | 003       | commercial
       2 | 007       | commercial
       0 | 001       | commercial
       1 | 004       | residential
       0 | 002       | residential
       2 | 006       | residential
    (7 rows)

### See Also

ST_ClusterDBSCAN, ST_ClusterIntersecting, ST_ClusterWithin, ST_Subdivide

ST_ClusterWithin

Aggregate function that clusters the input geometries by separation distance.

                geometry[] ST_ClusterWithin
                geometry set  g
                float8  distance

### Description

ST_ClusterWithin is an aggregate function that returns an array of GeometryCollections, where each GeometryCollection represents a set of geometries separated by no more than the specified distance. (Distances are Cartesian distances in the units of the SRID.)

Availability: 2.2.0

### Examples

    WITH testdata AS
      (SELECT unnest(ARRAY['LINESTRING (0 0, 1 1)'::geometry,
    		       'LINESTRING (5 5, 4 4)'::geometry,
    		       'LINESTRING (6 6, 7 7)'::geometry,
    		       'LINESTRING (0 0, -1 -1)'::geometry,
    		       'POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))'::geometry]) AS geom)

    SELECT ST_AsText(unnest(ST_ClusterWithin(geom, 1.4))) FROM testdata;

    --result

    st_astext
    ---------
    GEOMETRYCOLLECTION(LINESTRING(0 0,1 1),LINESTRING(5 5,4 4),LINESTRING(0 0,-1 -1),POLYGON((0 0,4 0,4 4,0 4,0 0)))
    GEOMETRYCOLLECTION(LINESTRING(6 6,7 7))

### See Also

ST_ClusterDBSCAN, ST_ClusterKMeans, ST_ClusterIntersecting