Given data points with longitude, latitude, and a third property value of this point. How can I cluster points into groups (geographical sub-regions) based on the property value? I searched by google and figured out that this problem seems to be called "spatial constrained clustering" or "regionalizing". However, I am not familiar with handling geographical data and haven't get an idea about what kind of algorithms are good, and which python/R packages are good for this task.

To give a more intuitive idea about what I want, let's say my data scatter plots are as following: enter image description here

So each dot is a point, x is longitude, y is latitude, and colormap shows whether the value is big or small. I want to divide those points into sub regions/groups/clusters based on location and similarity of values. Like the following (it is not exactly what I want, just to show a intuitive idea.): enter image description here

So how can I achieve this?

  • Your question is a bit broad as it stands. Have you tried any of the R or Python packages out? Commented May 25, 2016 at 7:33
  • @JohnBarça Currently I think clusterPy package seems useful and rise-group.org/risem/clusterpy/clusterpy0_9_9/… shows how to use it. However, my data is three column points: latitude, longitude, and value. I wish to divide points into sub-region groups based on point value. The package input format seems like some polygon or grid, and I haven't figure out how to directly use it to handle spatial points.
    – Excalibur
    Commented May 25, 2016 at 7:38
  • 1
    check out the related questions to your question, e.g.: gis.stackexchange.com/questions/17638/…
    – Iris
    Commented May 25, 2016 at 9:55
  • @Iris Thanks! I have checked the webpage, but seems I still cannot find a way to handle such 3 column spatial points with property directly.
    – Excalibur
    Commented May 25, 2016 at 18:02
  • @Excalibur for any geographical clustering I would currently recommend HDBScan. In regards to your third value, this could be seen as some kind of weight, I guess. Without projecting all of the values into the same space, this could be a tricky task. Can you provide some background info regarding your objective? Commented May 28, 2016 at 18:13

1 Answer 1


The rioja package provides functionality for constrained hierarchical clustering. For what your are thinking of as "spatially constrained" your would specify your cuts based on distance whereas for "regionalization" you could use k nearest neighbors. I would highly recommend projecting your data so it is in a distance based coordinate system.


  coordinates(meuse) <- ~x+y
  cdat <- data.frame(x=coordinates(meuse)[,1],y=coordinates(meuse)[,2])
  rownames(cdat) <- rownames(meuse@data)

# Constrained hierarchical clustering 
chc <- chclust(dist(cdat), method="conslink")

# Using kNN with 3 neighbors
chc.n3 <- cutree(chc, k=3) 

# Using distance 
chc.d200 <- cutree(chc, h=200) 

meuse@data <- data.frame(meuse@data, KNN=as.factor(chc.n3), DClust=chc.d200)

opar <- par
   cols <- topo.colors(length(unique(meuse@data$KNN)))  
    color <- rep("xx", nrow(meuse@data))
      for(i in 1:length(unique(meuse@data$KNN))) {
        v <- unique(meuse@data$KNN)[i] 
          color[(meuse@data$KNN == v)] <- cols[i]
    plot(meuse, col=color, pch=19, main="kNN Clustering")

    cols <- topo.colors(length(unique(meuse@data$DClust)))  
    color <- rep("xx", nrow(meuse@data))
      for(i in 1:length(unique(meuse@data$DClust))) {
        v <- unique(meuse@data$DClust)[i] 
          color[(meuse@data$DClust == v)] <- cols[i]
    plot(meuse, col=color, pch=19, main="Distance Clustering")
par <- opar
  • 1
    Hi @JeffreyEvans, thanks for your reply! So you are suggesting that I project the third property value into another kind of coordinate right? However, I think there should be some existing algorithms that distinguish (lon, lat) with associated attributes, and then do clustering and make points into continuous regions, and points in the same regions shall have similar values (of course there are some outliers). Is there any package can achieve this? I updated my problem for a more intuitive example. Thanks.
    – Excalibur
    Commented May 25, 2016 at 21:37

Not the answer you're looking for? Browse other questions tagged or ask your own question.