Добавьте метки цветовых полос в виде текста на графике - PullRequest
0 голосов
/ 21 января 2020

У меня есть точечная диаграмма, сгенерированная с использованием:

x = list(auto['umap1'])
y = list(auto['umap2'])


final_df2 = pd.DataFrame(list(zip(x,y,communities)), columns =['x', 'y', 'cluster'])
no_clusters = max(communities)
cluster_list = list(range (min(communities), no_clusters+1))
fig2, ax = plt.subplots(figsize = (20,15))
plt.scatter(x,y, c=final_df2['cluster'], cmap=plt.cm.get_cmap('hsv', max(cluster_list)), s = 0.5)
plt.title('Phenograph on UMAP - All Markers (auto)', fontsize=15)
plt.xlabel('umap_1', fontsize=15)
plt.ylabel('umap_2', fontsize=15)
plt.colorbar(extend='both',ticks = range(max(cluster_list)))
plt.show()

Я хотел бы знать, как я могу добавить метки цветовых полос (числа от 1 до 31) к фактическим кластерам на графике (в виде текста), которые каждый соответствует. Это потому, что довольно трудно отличить это от цветов, поскольку они возвращаются к красному.

Я пытался:

n = list(final_df2['cluster'])
for i, txt in enumerate(n):
    ax.annotate(txt, (y[i], x[i]))

Но это не дает мне удачи. enter image description here

1 Ответ

2 голосов
/ 21 января 2020

Ваш код для аннотаций записывает аннотации для каждой точки. Это просто заканчивается в море чисел.

Каким-то образом вы должны найти своего рода центр для каждого кластера, например, путем усреднения всех точек, принадлежащих одному кластеру.

Затем, Вы используете координаты центра, чтобы расположить текст. Вы можете создать фон, чтобы его было легче читать.

Поскольку у меня нет ваших данных, приведенный ниже код имитирует некоторые точки уже вокруг центра.

from matplotlib import pyplot as plt
import pandas as pd
import numpy as np

# calculate some random points to serve as cluster centers; run a few steps of a relaxing algorithm to separate them a bit
def random_distibuted_centers():
    cx = np.random.uniform(-10, 10, MAX_CLUST + 1)
    cy = np.random.uniform(-10, 10, MAX_CLUST + 1)
    for _ in range(10):
        for i in range(1, MAX_CLUST + 1):
            for j in range(1, MAX_CLUST + 1):
                if i != j:
                    dist = np.linalg.norm([cx[i] - cx[j], cy[i] - cy[j]])
                    if dist < 4:
                        cx[i] += 0.4 * (cx[i] - cx[j]) / dist
                        cy[i] += 0.4 * (cy[i] - cy[j]) / dist
    return cx, cy

N = 1000
MAX_CLUST = 31
cx, cy = random_distibuted_centers()

# for demonstration purposes, just generate some random points around the centers
x =  np.concatenate( [np.random.normal(cx[i], 2, N) for i in range(1,MAX_CLUST+1)])
y =  np.concatenate( [np.random.normal(cy[i], 2, N) for i in range(1,MAX_CLUST+1)])
communities = np.repeat(range(1,MAX_CLUST+1), N)

final_df2 = pd.DataFrame({'x':x, 'y':y, 'cluster': communities})
no_clusters = max(communities)
cluster_list = list(range (min(communities), no_clusters+1))
fig2, ax = plt.subplots(figsize = (20,15))
plt.scatter(x,y, c=final_df2['cluster'], cmap=plt.cm.get_cmap('hsv', max(cluster_list)), s=0.5)
plt.title('Phenograph on UMAP - All Markers (auto)', fontsize=15)
plt.xlabel('umap_1', fontsize=15)
plt.ylabel('umap_2', fontsize=15)
plt.colorbar(extend='both',ticks = cluster_list)

bbox_props = dict(boxstyle="circle,pad=0.3", fc="white", ec="black", lw=2, alpha=0.9)
for i in range(1,MAX_CLUST+1):
    ax.annotate(i, xy=(cx[i], cy[i]), ha='center', va='center', bbox=bbox_props)
plt.show()

example plot

...