# Custom distance metric for agglomerative clustering in Mathematica

Is it possible to have a custom distance metric defined to determine the distance between two clusters in Agglomerative clustering in Mathematica?

I have a 3 dimension data with string values along all three dimensions.

I want to define my own way of measuring the distance between any two clusters (Strings here...)

Also, I want to stop the clustering when the distance between two clusters is greater than a particular threshold value "T".

Is this available in Mathematica?

-

## migrated from stackoverflow.comApr 20 '12 at 12:53

This question came from our site for professional and enthusiast programmers.

By using the HierarchicalClustering package, you can define your own DistanceFunction between clusters. See for example reference.wolfram.com/mathematica/HierarchicalClustering/ref/… (option DistanceFunction) – Dr. belisarius Apr 19 '12 at 4:26
Thanks. Looked at it. It says that we can define our own DistanceFunction, but I am still wondering how do you instruct Mathematica to stop clustering if the distance is greater than "T" between two clusters for a "Complete" type of Linkage? Where do we specify this condition? – Abhishek Shivkumar Apr 19 '12 at 9:51

The tutorial tutorial/PartitioningDataIntoClusters has information on Distance functions (also for Strings, e.g. HammingDistance).

-
But there there is no reference nor examples on how to use a custom linkage function. – Dr. belisarius Apr 22 '12 at 23:05

Not as a built in function. You will have to write your own. Fortunately it's quite easy and the benefit is you now have a function that provides the custom distance important to your data.

euclidianDistance[{x_List, y_List,
z_List}, {xX_List, xY_List,
xZ_List}] := Block[{ed, dist, len, lenp},
len = Length[xX];
lenp = Length[x];
If [len != lenp,
Print["euclidianDistance:Standard and Sample sizes do not match"]];
ed = Table[((x[[i]] -
xXL[[i]])^2 + (y[[i]] -
xY[[i]])^2 + (z[[i]] -
xZ[[i]])^2)^0.5, {i, 1, len}];
dist = Chop[ed /. n_ /; n <= 0 -> 0.000000001]
]


Here's an easy example of Euclidian Distance.

-
Thanks Hall. But where can I mention the threshold value "T" that if the custom distance between two clusters is less than "T", then it should not proceed with clustering these two clusters in agglomerative clustering? – Abhishek Shivkumar Apr 19 '12 at 15:14
Also, can you just explain your last statement about CHOP please? Thanks – Abhishek Shivkumar Apr 19 '12 at 15:28
@AbhishekShivkumar You will need to ad an If statement that provides the custom T factor your looking for. Something Like: If[T>1, do something, or else this]; The last statement, simply replaces approximate real numbers in the expr that are close to zero by the exact integer 0. and uses Rule replacement to make them a trivial non Zero value thats valuable if your functions do not handle zero values well. – R Hall Apr 19 '12 at 23:33
Hall, thanks. Do you know where I should add such a statement? Here is my code: myDistance[{x_List, y_List, z_List}, {xX_List, xY_List, xZ_List}] := Block[{ed, dist, len, lenp}, len = Length[xX]; lenp = Length[x]; If [len != lenp, Print["euclidianDistance:Standard and Sample sizes do not match"]]; ed = Table[((x[[i]] - xXL[[i]])^2 + (y[[i]] - xY[[i]])^2 + (z[[i]] - xZ[[i]])^2)^0.5, {i, 1, len}]; dist = Chop[ed /. n_ /; n <= 0 -> 0.000000001] ] dataF = {{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, {4, 5, 6}}; c = FindClusters[dataF, Method -> {"Agglomerate"}, DistanceFunction -> myDistance] – Abhishek Shivkumar Apr 20 '12 at 3:20
@AbhishekShivkumar The distance function must be run first, then use that variable to find clusters based on the If statement. – R Hall Apr 20 '12 at 11:23