No post de análise de cluster, foram utilizados algoritmos de agrupamento para classificar dados. No entanto, os números de cluster atribuídos não têm uma ordem. Na verdade, são números apenas por conveniência – poderiam ser letras também. Quando fizer mais de uma rodada ou for comparar resultados de diferentes séries, isso acaba sendo um grande problema. Se você deseja impor uma ordem ou nomes específicos a eles, você pode rotulá-los novamente como quiser, já que isso não é função do algoritmo de agrupamento. Por exemplo, você pode classificar os centros pela coordenada X e remarcá-los.
Como o início da localização dos grupos é randômica, a combinação “cor x número do grupo” pode variar a cada rodada no gráfico. Um primeiro passo pode ser o de fixar a semente inicial através do parâmetro “random_state=0”. No entanto, se quiser que os rótulos (‘labels’) de cada grupo permaneçam em uma certa sequência, isso não garante uma correlação correta entre rótulo dado pelo algoritmo e o que você deseja.
No exemplo a seguir, é criado um vetor com as classes desejadas, que são números de 1 a 20 (‘day_classes’). Também é criado um vetor com os números dos clusters calculados pelo algoritmo, que são de 0 a 19 (‘cluster_numbers’) e calculado outro vetor com as médias da variável ‘qs’ para cada agrupamento (‘mean_classes’), posteriormente unidos em um dicionário. Cada item desse dicionário é composto por chave (número do agrupamento) e valor (média de ‘qs’ do agrupamento). Posteriormente, ele é ordenado pelo valor de ‘qs’ e extraída uma lista somente com as chaves (‘before’). O vetor ‘after’ será o ordenamento final, formado pelo vetor de classes desejadas.
Para renomear as classes originais dos agrupamentos (‘before’) para a nova sequência desejada (‘after’) diretamente na coluna de rótulos do dataframe original (df[‘label’]), deve ser criada uma máscara indicando a posição de cada número (‘mdk’). Em seguida, essa máscara é aplicada na coluna com os rótulos originais. Pronto, a dataframe está com os rótulo redefinidos – nesse caso, seguindo uma ordem de 1 a 20 conforme o valor de uma das variáveis.
O método definido a seguir recebe a dataframe contendo os dados a serem agrupados e uma lista com o nome das colunas a serem utilizadas (duas ou três variáveis). São fixados 20 agrupamentos, cujas variáveis são selecionadas da dataframe e servem de entrada para o método de cálculo do k-means. Os rótulos são guardados em uma coluna da dataframe, que é renomeada conforme já foi descrito. Por fim, são feitos gráficos das variáveis, com opções 2D e 3D (as cores indicam o número de cada classe).
from sklearn.cluster import k_means from matplotlib import pyplot as plt from mpl_toolkits import mplot3d def kmeans(df, var_lst): n_clusters = 20 # Create numpy.ndarray selecting columns data = df.loc[:, var_lst].values centroids, labels, sse = k_means(data, n_clusters=n_clusters, random_state=0, n_init=100) df['label'] = labels ## Sort Clusters ## # Calculate QS mean from every class day_classes = list(range(1, n_clusters+1)) cluster_numbers = list(range(0, n_clusters)) mean_classes = [0] * n_clusters for x in range(n_clusters): selection = df[df['label'] == x] mean_classes[x] = selection['qs'].mean() clusters_info = dict(zip(cluster_numbers, mean_classes)) # Sort dictionary by value clusters_sorted = {k: v for k, v in sorted(clusters_info.items(), key=lambda item: item[1])} # Create lists from key values before = list(clusters_sorted.keys()) after = day_classes # Relabel classes numbers according to QS values mdk = [df['label'] == i for i in before] for l in range(len(after)): #df['label'][mdk[l]] = after[l] #SettingWithCopyWarning df.loc[mdk[l], 'label'] = after[l] ################### # 2D plot plt.scatter(df['qs'], df['label'], c=df['label'], cmap='jet') plt.title('Classes numbers according QS values') plt.xlabel('QS') plt.ylabel('Day Class') plt.ylim(0, 20) plt.yticks(np.arange(0, 20, 2)) plt.show() # 3D Plot fig = plt.figure() ax = plt.axes(projection="3d") ax.scatter3D(df[var_lst[0]], df[var_lst[0]], df[var_lst[0]], c=df['label'], cmap='jet') ax.set_xlabel(var_lst[0].upper()) ax.set_ylabel(var_lst[1].upper()) ax.set_zlabel(var_lst[2].upper()) plt.show()
Veja como agora os valores médios de QS ordenados definem os números das classes calculadas pelo algoritmo k-means (antes e depois):
Uma forma alternativa de realizar essa reordenação pode ser vista no Stackoverflow – How to set k-Means clustering labels from highest to lowest with Python?
One comment