Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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.

share|improve this question
    
You've tried playing around with various DistanceFunction settings? DistanceFunction -> BrayCurtisDistance and DistanceFunction -> CanberraDistance work here, for instance... –  J. M. Oct 27 '12 at 17:10
    
@J.M. Sorry, posted an answer simultaneously –  belisarius Oct 27 '12 at 17:13
    
@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... –  J. M. Oct 27 '12 at 17:15
    
@J.M. added a "testing framework" (so to speak) –  belisarius Oct 27 '12 at 17:37
    
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. –  Sven K Oct 27 '12 at 17:45
show 7 more comments

2 Answers

up vote 8 down vote accepted

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

share|improve this answer
    
Neat addition. :) OP should now be able to play around with the Method and DistanceFunction options easily, to see what suits his data best. –  J. M. Oct 27 '12 at 17:39
add comment

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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