Como Trabalhar com Clustering em Python
Aspose.PDF FOSS para Python inclui uma pequena utilidade de clustering hierárquico aglomerativo de uso geral — independente de qualquer operação única de PDF — para agrupar objetos DataPoint relacionados em instâncias Cluster e calcular o centróide de um cluster. Você decide o que cada ponto de dados representa e fornece suas coordenadas manualmente; a utilidade não as preenche automaticamente. A biblioteca é instalada com o comando abaixo.
Guia passo a passo
Etapa 1: Instalar o pacote
Instale o pacote FOSS Aspose.PDF:
git clone https://github.com/aspose-pdf-foss/Aspose-PDF-FOSS-for-Python.git
cd Aspose-PDF-FOSS-for-Python
pip install -e .Verifique a instalação importando Cluster e imprimindo uma mensagem de confirmação:
from aspose_pdf import Cluster
print("aspose-pdf-foss-for-python is ready.")Etapa 2: Importar Classes Necessárias
Importe as três classes que compõem a utilidade de clustering:
from aspose_pdf import Cluster, ClusterCollection, DataPointEtapa 3: Criar Pontos de Dados
Um DataPoint combina uma string name com uma lista value de floats — as coordenadas ou vetor de características que você decidir que são significativas para a sua própria lógica de agrupamento:
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 não vincula value a nenhum conceito específico de PDF — coordenadas de página, métricas de fonte ou qualquer outro vetor de características numéricas funcionam igualmente bem.
Etapa 4: Agrupar Pontos de Dados em um Cluster
Passe a lista completa de membros para o construtor Cluster. Não há método para adicionar itens a um Cluster depois que ele é criado, portanto decida a membresia primeiro:
from aspose_pdf import Cluster
nearby = Cluster([point_a, point_b])
print(nearby.count) # 2
print(nearby.contains(point_a)) # Truecontains() corresponde por igualdade — DataPoint define igualdade com base em name e value juntos, de modo que uma instância diferente de DataPoint com o mesmo nome e valor também é relatada como contida.
Etapa 5: Calcular o centróide do cluster
DataPoint.get_centroid(cluster) é um método estático que calcula a média de cada dimensão de cada DataPoint.value no cluster e retorna o resultado como um novo DataPoint chamado "centroid":
from aspose_pdf import DataPoint
centroid = DataPoint.get_centroid(nearby)
print(centroid.name) # "centroid"
print(centroid.value) # per-dimension average across the clusterCada lista DataPoint.value no cluster deve ter o mesmo comprimento — get_centroid calcula a média posição por posição e não valida se os comprimentos coincidem. Chamá-la em Cluster.empty(), ou em qualquer cluster com count == 0, gera ValueError.
Etapa 6: Clonar um cluster ou reutilizar a instância vazia compartilhada
clone() retorna um Cluster independente contendo os mesmos itens; Cluster.empty() sempre devolve a mesma instância de cluster vazio em cache, em vez de alocar uma nova:
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) # 0Etapa 7: Agrupar múltiplos clusters em um ClusterCollection
ClusterCollection agrupa vários objetos Cluster por trás de um único contêiner compatível com len():
from aspose_pdf import Cluster, ClusterCollection
outliers = Cluster([point_c])
collection = ClusterCollection([nearby, outliers])
print(len(collection)) # 2ClusterCollection não expõe um método para recuperar seus clusters — mantenha uma referência à lista que você passa ao construtor se precisar iterar sobre os clusters posteriormente.
Problemas Comuns e Soluções
Não há método para adicionar um item a um existente Cluster
Cluster só aceita sua lista de membros no momento da construção (Cluster(items)). Construa a lista completa de objetos DataPoint primeiro, depois crie o Cluster — não há add() ou append() para chamar depois.
DataPoint.get_centroid() raises ValueError
Isso acontece quando o cluster passado está vazio (count == 0), incluindo Cluster.empty(). Verifique cluster.count antes de chamar get_centroid, ou trate a exceção se um cluster vazio for uma entrada válida em seu fluxo de trabalho.
Os valores do centróide parecem errados
get_centroid soma cada posição DataPoint.value por posição e divide pelo número de pontos — não verifica se cada lista value no cluster tem o mesmo tamanho. Misturar objetos DataPoint com dimensionalidade incompatível produz uma média incorreta silenciosamente em vez de gerar um erro.
Expecting Cluster.empty() para criar um cluster vazio novo a cada vez
Cluster.empty() é um acessor singleton — cada chamada retorna a mesma instância em cache. Use Cluster() (sem argumentos) em vez disso se precisar de um cluster vazio distinto e independente.
Esperando que a biblioteca agrupe pontos automaticamente
DataPoint, Cluster e ClusterCollection são estruturas de dados para representar pontos, clusters e um cálculo de centróide — o módulo não inclui uma função de ligação ou distância que decida quais pontos pertencem juntos. Seu próprio código determina a associação ao cluster antes de construir um Cluster.
Perguntas Frequentes
Este módulo agrupa automaticamente os pontos de dados por distância?
Não. Cluster, DataPoint e ClusterCollection são blocos de construção para representar agrupamentos já decididos e calcular um centróide — não há etapa incorporada de aglomeração ou atribuição baseada em distância.
Qual é a diferença entre Cluster() e Cluster.empty()?
Cluster(items=None) cria uma nova instância toda vez que é chamado. Cluster.empty() é um classmethod que retorna a mesma instância de cluster vazio em cache e compartilhada em cada chamada.
Posso adicionar itens a um Cluster depois de criá-lo?
Não. Cluster só expõe contains(), clone() e a propriedade count além da construção — a composição fica fixa assim que o construtor é executado.
O get_centroid() funciona com qualquer número de dimensões?
Sim, desde que cada lista DataPoint.value no cluster tenha o mesmo comprimento. get_centroid calcula a média de cada dimensão independentemente e devolve o resultado como um novo DataPoint.
O que ClusterCollection adiciona além de uma simples lista Python de clusters?
Principalmente um contêiner tipado com suporte a len(). Ele não adiciona iteração, busca ou comportamento de mesclagem além do que você já tem na lista a partir da qual o construiu.