# K Mean

K-means stores **k** centroids that it uses to define clusters. A point is considered to be in a particular cluster if it is closer to that cluster's centroid than any other centroid.

![Grouping points into k (no.s) clusters](https://1430428134-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Ld8QK19sjP1I9rhLouo%2F-MjDvmtTH-1l6R84mCcw%2F-MjDw6lFpiVErPvKSEF4%2FKmeans-20210910-1_2021-09-10_02-25-22.png?alt=media\&token=6cc475fa-ac14-4500-8e9c-ed1b91e56d6e)

<https://stanford.edu/~cpiech/cs221/handouts/kmeans.html>

```d
// Group by Centroid
def k1(pnts:var[]..[],cnts:var[]..[])
{
	//Labels
	lbl1 = "A"..#(List.Count(cnts))..1;

	//Distance to Centroids
	dst1 = pnts<1>.DistanceTo(cnts<2>);
	dst2 = List.SortByKey(lbl1,dst1<1>);
	dst3 = List.FirstItem(dst2["sortedList"]<1>);

	//Group by Closest to Centroid
	pnt1 = List.GroupByKey(pnts,dst3)["groups"];
	return pnt1;
};

// Centroid
def ctr (pnts:var[]..[])
{
	return Point.ByCoordinates(Math.Average(pnts.X),
	Math.Average(pnts.Y),Math.Average(pnts.Z));
};

// K Mean
def kMean (pnts:var[]..[],k:int)
{
	pnt1 = k1(pnts,pnts[1..k]);
	cnt1 = 1;
	pnt2 = [];
	pts1 = [Imperative]
	{
		while (cnt1 <= k)
		{
			ctr1 = ctr(pnt1);
			pnt2 = k1(List.Flatten(pnt1,-1),ctr1);
			cnt1 = cnt1 + 1;
			pnt1 = pnt2;
		}
		return pnt2;
	}
	return pts1;
};
```
