В этой задаче библиотека scikit-learn нам не поможет, поэтому обратимся к SciPy. Для начала следует воспользоваться функцией linkage из scipy.cluster.hierarchy, которая и проведет процесс кластеризации (ранее я разбирал ее работу). В третьей колонке она возвращает дистанцию между объединяемыми кластерами (из первого и второго столбцов). На ее основании можно и задать предельный порог, после которого дистанция считается существенной и кластера перестают объединяться:
Мера дистанции
Имея результат linkage, можно применить функцию fcluster того же модуля для присвоения меток кластеров. Однако до этого под капотом она подбирает их количество в соответствии с пороговым значением t для дистанции при заданном параметре criterion='distance' (с дистанцией больше, чем порог, кластера не объединяются):
Отмечу, что для подбора подходящего t удобно вывести гистограмму дистанций и квантили различного уровня с методами hist и quantile (например, link_df['dist'].quantile(.8)).
Мера "непоследовательности"
Ее можно использовать как альтернативу метрике дистанции между кластерами. Для подсчета используйте функцию inconsistent все того же модуля scipy.cluster.hierarchy. Она возвращает матрицу, в i-ой строке которой расположены средние и стандартные отклонения дистанций между кластерами (первые 2 колонки), начиная от заданного на d уровней вниз, количество связей (3 колонка) и сам коэффициент (4 столбец):
Коэффициенты считаются как разность дистанции для i-го кластера (Zi) и среднего, деленная на стандартное отклонение:
Рассмотрим примеры подсчета.
clust 11
Получен объединением кластеров 1 и 8 (из точек с индексами 5 и 6). Дистанция для clust 11 - 1.154701, у clust 8 - 0:
clust 12
получен объединением 9([2,7]) и 10 ([0,4])
clust 14
Давайте пересчитаем меру с глубиной 3:
Теперь можно аналогично кластеризации с заданным порогом для дистанции, провести разбиение по мере "непоследовательности":