I'm having some problems clustering data in a 2D spectra and will really appreciate some help. I've been playing around with the FindClusters function but wasn't able to tune it appropriately. Maybe someone can give me a hand on how to customize the DistanceFunction option or so.

A sample of my data looks like this:

Sample data

Ideally I would want the peaks to be clustered as this:

Ideal clustering

I tried the FindClusters functions with different parameters but only got partial clusters like these:

Partial clusters

I believe it may be easy if I can define my own DistanceFunction but I don't understand how to use a custom function there with a threshold or so.

I've seen other posts like this one, this other one and this one too but I wasn't able to successfully apply those methods.

It doesn't matter if I don't get that red circle clustering like the ideal image. If I can just get to identify the whole clusters, I can reduce that set to just one point that would be the center of gravity.

It would be awesome if you can point me the way on how to solve this. You can download that sample from here.

Just one thing, I don't know before hand how many clusters I'll get. I believe there are 30 in this dataset but this is just a sample. Thank you!!

  • $\begingroup$ I will give you two links to read First and Second $\endgroup$
    – Sektor
    Commented Sep 1, 2013 at 2:02
  • $\begingroup$ Those were the first things I read but couldn't understand how a custom DistanceFunction works $\endgroup$
    – xtian777x
    Commented Sep 1, 2013 at 2:27
  • $\begingroup$ Well, you need to make up your mind how do you want to partition the set of data/measurements. You need to define a metric and based on that proceed with implementing the DistanceFunction[]. Long story - short - on what similar characteristic do you plan to partition the set of data ? $\endgroup$
    – Sektor
    Commented Sep 1, 2013 at 2:41
  • $\begingroup$ OK, let's say I use the default EuclideanDistance function, how do I know what is the threshold it's using to discriminate? Like "points with distance < 0.5 between them are considered a cluster"? My guess is that, if the DistanceFunction f satisfies f(ei,ej)>0, I would have to make a function that, for distances greater than 0.5 => f(ei,ej)<0. In that sense, f will no longer fulfill the condition and those points will be left outside the cluster. Makes sense? Thanx! $\endgroup$
    – xtian777x
    Commented Sep 1, 2013 at 2:55
  • $\begingroup$ To answer the question what threshold is used in the algorithms you should read this general method Link $\endgroup$
    – Sektor
    Commented Sep 1, 2013 at 3:25

2 Answers 2


Inspired by Murta answer I have this one:

  With[{list = 
   Join @@ (Split[
     SortBy[#, Last], (Abs[(#1[[2]] - #2[[2]])] < limY) &] & /@ 
     Gather[datapairs, Abs[(#1[[1]] - #2[[1]])] < limX &])}, 
   Column[{ListPlot[list, ImageSize -> 400], 
    Row[{"Number of clusters:", Length[list]}]}]]
  , {{limY, 5}, 0, 50}, {{limX, 5}, 0, 50}]

manipulate output

I split first by column and then by the other axis.


This can be a first step.

 dataC = Mean /@ Gather[datapairs, EuclideanDistance[#1, #2] < lim &];
 p1 = ListPlot[datapairs];
 p2 = ListPlot[dataC, PlotStyle -> Directive[Opacity[0.5], PointSize[0.02], Red]];
 Show[p2, p1]
 , {lim, 5, 50, 10}

enter image description here


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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