8
$\begingroup$

I am trying to use FindClusters to segment data points into similar numbers but so far I couldn't get it work for this example:

l = {110, 111, 115, 117, 251, 254, 254, 259, 399, 400, 401, 
     402, 542, 546, 549, 554, 660, 660, 660, 660};
FindClusters[l]
(*
-> {{110, 111, 115, 117, 251, 254, 254, 259, 399, 400, 401, 402, 542, 
   546, 549, 554, 660, 660, 660, 660}}
*)

If I set the N parameter (to specify: Exactly N clusters), it works:

FindClusters[l, 5]
(*
-> {{110, 111, 115, 117}, {251, 254, 254, 259}, 
    {399, 400, 401, 402}, {542, 546, 549, 554}, {660, 660, 660, 660}}
*)

However, my intent was to use FindClusters to figure out N.

$\endgroup$
12
  • $\begingroup$ You've tried playing around with various DistanceFunction settings? DistanceFunction -> BrayCurtisDistance and DistanceFunction -> CanberraDistance work here, for instance... $\endgroup$ Commented Oct 27, 2012 at 17:10
  • $\begingroup$ @J.M. Sorry, posted an answer simultaneously $\endgroup$ Commented Oct 27, 2012 at 17:13
  • $\begingroup$ @bel, no prob, though I have a feeling we got lucky, and these only work for the particular case that OP presented, since OP says nothing more about the nature of the actual data... $\endgroup$ Commented Oct 27, 2012 at 17:15
  • $\begingroup$ @J.M. added a "testing framework" (so to speak) $\endgroup$ Commented Oct 27, 2012 at 17:37
  • $\begingroup$ Thanks for your answers! I am still trying to figure out why EuclideanDistance doesn't work in this case. @J.M.: context is a an OCR algorithm I am trying to implement. I am trying to normalize a grid that has been estimated by WatershedComponents (See my other question) . It's probably too complex to include here. $\endgroup$
    – Sven K
    Commented Oct 27, 2012 at 17:45

2 Answers 2

8
$\begingroup$

Use the Bray-Curtis distance Total[Abs[u-v]]/Total[Abs[u+v]]:

FindClusters[{110, 111, 115, 117, 251, 254, 254, 259, 399, 400, 401, 
              402, 542, 546, 549, 554, 660, 660, 660, 660}, 
              DistanceFunction -> BrayCurtisDistance]
(*
{{110, 111, 115, 117}, 
 {251, 254, 254, 259}, 
 {399, 400, 401, 402},
 {542, 546, 549, 554}, 
 {660, 660, 660, 660}}
*)

Edit:

Here you have an experimental setup to test the FindClusters[] options in problems like yours:

l1 = RandomInteger[{100, 1000}, 10];
l2 = Join @@ (IntegerPart /@ RandomVariate[NormalDistribution[#, 10], 10] & /@ l1);
l3 = FindClusters[l2, DistanceFunction -> CanberraDistance];
Framed@Show[MapIndexed[
            Graphics[{ColorData[3][#2[[1]]],
                     Line[{{#, 0}, {#, 1}}] & /@ #1}] &, l3], 
            PlotRange -> {0, 1}, AspectRatio -> 1/5]

Mathematica graphics

$\endgroup$
1
  • $\begingroup$ Neat addition. :) OP should now be able to play around with the Method and DistanceFunction options easily, to see what suits his data best. $\endgroup$ Commented Oct 27, 2012 at 17:39
2
$\begingroup$

I'm not really sure why the default option for FindClusters with EuclideanDistance and Method->"Optimize" fails to distinguish any clusters.

Here are some results which might add a little detail:

Here are the numeric distance functions:

dfs = {EuclideanDistance, SquaredEuclideanDistance, NormalizedSquaredEuclideanDistance, 
ManhattanDistance, ChessboardDistance, BrayCurtisDistance, CanberraDistance, 
CosineDistance, CorrelationDistance}

Applying the various distance functions and methods:

Length@FindClusters[l, DistanceFunction -> #, Method -> "Agglomerate"] & /@ dfs
Length@FindClusters[l, DistanceFunction -> #, Method -> "Optimize"] & /@ dfs

{5, 1, 1, 5, 5, 5, 5, 1, 1} {1, 1, 1, 1, 1, 5, 5, 1, 1}

And in tabular form:

Mathematica graphics

So it is possible to use the EuclideanDistance function for this data, but only with agglomerative clustering.

$\endgroup$

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.