Как работать с кластеризацией в Python
Aspose.PDF FOSS for Python поставляет небольшую, универсальную иерархическую агломеративную утилиту кластеризации — независимую от любой отдельной операции с PDF — для группировки связанных объектов DataPoint в экземпляры Cluster и вычисления центроида кластера. Вы решаете, что представляет собой каждая точка данных, и задаёте её координаты самостоятельно; утилита не заполняет их автоматически. Библиотека устанавливается командой ниже.
Пошаговое руководство
Шаг 1: Установить пакет
Установите пакет Aspose.PDF FOSS:
git clone https://github.com/aspose-pdf-foss/Aspose-PDF-FOSS-for-Python.git
cd Aspose-PDF-FOSS-for-Python
pip install -e .Проверьте установку, импортировав Cluster и выведя сообщение подтверждения:
from aspose_pdf import Cluster
print("aspose-pdf-foss-for-python is ready.")Шаг 2: Импортировать необходимые классы
Импортируйте три класса, составляющих утилиту кластеризации:
from aspose_pdf import Cluster, ClusterCollection, DataPointШаг 3: Создать точки данных
Объект DataPoint связывает строку name со списком value из чисел с плавающей точкой — координаты или вектор признаков, которые вы считаете значимыми для своей логики группировки:
from aspose_pdf import DataPoint
point_a = DataPoint("item-1", [12.0, 45.0])
point_b = DataPoint("item-2", [13.5, 44.0])
point_c = DataPoint("item-3", [98.0, 5.0])
print(point_a.name, point_a.value)DataPoint не связывает value с какой-либо конкретной концепцией PDF — координаты страниц, метрики шрифтов или любой другой числовой вектор признаков работают одинаково хорошо.
Шаг 4: Сгруппировать точки данных в кластер
Передайте полный список членов конструктору Cluster. После создания Cluster нет метода для добавления элементов, поэтому определите членство заранее:
from aspose_pdf import Cluster
nearby = Cluster([point_a, point_b])
print(nearby.count) # 2
print(nearby.contains(point_a)) # Truecontains() сравнивается по равенству — DataPoint определяет равенство по сочетанию name и value, поэтому другой экземпляр DataPoint с тем же именем и значением также считается содержащимся.
Шаг 5: Вычислить центр кластера
DataPoint.get_centroid(cluster) — это статический метод, который усредняет каждое измерение каждого DataPoint.value в кластере и возвращает результат в виде нового DataPoint с именем "centroid":
from aspose_pdf import DataPoint
centroid = DataPoint.get_centroid(nearby)
print(centroid.name) # "centroid"
print(centroid.value) # per-dimension average across the clusterКаждый список DataPoint.value в кластере должен иметь одинаковую длину — get_centroid усредняет позицию за позицией и не проверяет совпадение длины. Вызов его для Cluster.empty() или любого кластера с count == 0 вызывает ValueError.
Шаг 6: Клонировать кластер или повторно использовать общий пустой экземпляр
clone() возвращает независимый Cluster, содержащий те же элементы; Cluster.empty() всегда возвращает один и тот же кэшированный пустой экземпляр кластера вместо создания нового:
from aspose_pdf import Cluster
backup = nearby.clone()
print(backup is nearby) # False -- independent copy
print(backup.contains(point_a)) # True -- same items
placeholder = Cluster.empty()
print(placeholder.count) # 0Шаг 7: Объединить несколько кластеров в ClusterCollection
ClusterCollection объединяет несколько объектов Cluster за единым контейнером, поддерживающим len():
from aspose_pdf import Cluster, ClusterCollection
outliers = Cluster([point_c])
collection = ClusterCollection([nearby, outliers])
print(len(collection)) # 2ClusterCollection не предоставляет метод для извлечения своих кластеров — сохраните ссылку на список, переданный в конструктор, если вам понадобится позже перебирать кластеры.
Распространённые проблемы и решения
Нет метода добавить элемент к существующему Cluster
Cluster принимает список членов только во время создания (Cluster(items)). Сначала сформируйте полный список объектов DataPoint, затем создайте Cluster — после этого нет add() или append(), которые можно было бы вызвать.
DataPoint.get_centroid() raises ValueError
Это происходит, когда переданный кластер пуст (count == 0), включая Cluster.empty(). Проверьте cluster.count перед вызовом get_centroid или обработайте исключение, если пустой кластер является допустимым вводом в вашем рабочем процессе.
Значения центроидов выглядят неверно
get_centroid суммирует каждую позицию DataPoint.value по позициям и делит на количество точек — он не проверяет, что каждый список value в кластере имеет одинаковую длину. Смешивание объектов DataPoint с несоответствующей размерностью приводит к неверному среднему значению без предупреждения, а не к исключению.
Expecting Cluster.empty() создать новый пустой кластер каждый раз
Cluster.empty() — это одиночный аксессор, каждый вызов возвращает один и тот же кэшированный экземпляр. Используйте Cluster() (без аргументов) вместо него, если вам нужен отдельный, независимый пустой кластер.
Ожидая, что библиотека автоматически группирует точки
DataPoint, Cluster и ClusterCollection — это структуры данных для представления точек, кластеров и вычисления центроида — модуль не содержит функции связывания или расстояния, определяющей, какие точки принадлежат вместе. Ваш собственный код определяет принадлежность к кластеру перед созданием Cluster.
Часто задаваемые вопросы
Автоматически ли этот модуль группирует точки данных по расстоянию?
Нет. Cluster, DataPoint и ClusterCollection являются строительными блоками для представления уже определённых группировок и вычисления центроида — встроенного шага агрегации или назначения на основе расстояния нет.
В чём разница между Cluster() и Cluster.empty()?
Cluster(items=None) создает новый экземпляр каждый раз, когда вызывается. Cluster.empty() — это метод класса, который возвращает один и тот же кэшированный, общий пустой кластер при каждом вызове.
Могу ли я добавить элементы в Cluster после его создания?
Нет. Cluster раскрывает только contains(), clone() и свойство count помимо конструктора — состав фиксируется после выполнения конструктора.
Работает ли get_centroid() с любым количеством измерений?
Да, при условии, что каждый список DataPoint.value в кластере имеет одинаковую длину. get_centroid усредняет каждое измерение независимо и возвращает результат в виде нового DataPoint.
Что ClusterCollection добавляет к обычному списку кластеров Python?
В основном это типизированный контейнер с поддержкой len(). Он не добавляет итерацию, поиск или поведение слияния сверх того, что уже есть в списке, из которого вы его создали.