Wykres rozproszenia Matplotlib z innym tekstem w każdym punkcie danych

252

Usiłuję utworzyć wykres rozproszenia i opisać punkty danych różnymi liczbami z listy. Na przykład chcę wykreślić yvs xi opatrzyć adnotacjami odpowiednie liczby z n.

y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
z = [0.15, 0.3, 0.45, 0.6, 0.75]
n = [58, 651, 393, 203, 123]
ax = fig.add_subplot(111)
ax1.scatter(z, y, fmt='o')

Jakieś pomysły?

Labibah
źródło
Możesz także uzyskać wykres rozproszenia z etykietami podpowiedzi po najechaniu myszką za pomocą biblioteki mpld3. mpld3.github.io/examples/scatter_tooltip.html
Claude COULOMBE

Odpowiedzi:

466

Nie znam żadnej metody kreślenia, która bierze tablice lub listy, ale możesz jej użyć annotate()podczas iteracji po wartościach w n.

y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
z = [0.15, 0.3, 0.45, 0.6, 0.75]
n = [58, 651, 393, 203, 123]

fig, ax = plt.subplots()
ax.scatter(z, y)

for i, txt in enumerate(n):
    ax.annotate(txt, (z[i], y[i]))

Istnieje wiele opcji formatowania annotate(), patrz strona internetowa matplotlib:

wprowadź opis zdjęcia tutaj

Rutger Kassies
źródło
1
Działa również dobrze na Seaborn regplotbez większych zakłóceń.
ijoseph
@Rutger Używam ramki danych pandy i jakoś dostaję KeyError- więc zgaduję, że dict()obiekt jest oczekiwany? Czy jest jakiś inny sposób, aby oznaczyć dane używając enumerate, annotatei ramkę danych pandy?
Rachel
@Rachel, możesz użyć for row in df.iterrows():, a następnie uzyskać dostęp do wartości za pomocą row['text'], row['x-coord']itp. Jeśli opublikujesz osobne pytanie, przyjrzę się temu.
Rutger Kassies,
@RutgerKassies Dzięki, Rutger! Wysłałem tutaj pytanie stackoverflow.com/questions/41481153/ ... Obawiam się, że może być podobne do tego właśnie pytania. Ale nie mogę tego jakoś wypracować. Dziękuję za pomoc!
Rachel
1
@aviator, nie wbudowany niestety. Ale zobacz na przykład to za pomocą silnika układu Networkx: stackoverflow.com/a/34697108/1755432
Rutger Kassies
32

W wersji wcześniejszej niż matplotlib 2.0 ax.scatternie jest konieczne drukowanie tekstu bez znaczników. W wersji 2.0 musisz ax.scatterustawić odpowiedni zakres i znaczniki dla tekstu.

y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
z = [0.15, 0.3, 0.45, 0.6, 0.75]
n = [58, 651, 393, 203, 123]

fig, ax = plt.subplots()

for i, txt in enumerate(n):
    ax.annotate(txt, (z[i], y[i]))

I w tym linku możesz znaleźć przykład w 3d.

rafaelvalle
źródło
To jest niesamowite! Dziękujemy za udostępnienie tego rozwiązania. Czy możesz również udostępnić właściwy kod, aby ustawić rozmiar figury? Implementacje takie, plt.figure(figsize=(20,10))które nie działają zgodnie z oczekiwaniami, ponieważ wywoływanie tego kodu nie zmienia rozmiaru obrazu. Czekam na twoją pomoc. Dzięki!
Levine
rys., ax = plt. podploty (rys. rozmiar = (20,10))
rafaelvalle
21

W przypadku, gdy ktoś próbuje zastosować powyższe rozwiązania do .scatter () zamiast .subplot (),

Próbowałem uruchomić następujący kod

y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
z = [0.15, 0.3, 0.45, 0.6, 0.75]
n = [58, 651, 393, 203, 123]

fig, ax = plt.scatter(z, y)

for i, txt in enumerate(n):
    ax.annotate(txt, (z[i], y[i]))

Wystąpiły jednak błędy stwierdzające, że „nie można rozpakować nie iterowalnego obiektu PathCollection”, przy czym błąd wskazuje konkretnie na kodeline rys, ax = plt.scatter (z, y)

W końcu rozwiązałem błąd za pomocą następującego kodu

plt.scatter(z, y)

for i, txt in enumerate(n):
    plt.annotate(txt, (z[i], y[i]))

Nie spodziewałem się, że będzie różnica między .scatter () i .subplot (), powinienem był wiedzieć lepiej.

Heather Claxton
źródło
11

Możesz także użyć pyplot.text(patrz tutaj ).

def plot_embeddings(M_reduced, word2Ind, words):
""" Plot in a scatterplot the embeddings of the words specified in the list "words".
    Include a label next to each point.
"""
for word in words:
    x, y = M_reduced[word2Ind[word]]
    plt.scatter(x, y, marker='x', color='red')
    plt.text(x+.03, y+.03, word, fontsize=9)
plt.show()

M_reduced_plot_test = np.array([[1, 1], [-1, -1], [1, -1], [-1, 1], [0, 0]])
word2Ind_plot_test = {'test1': 0, 'test2': 1, 'test3': 2, 'test4': 3, 'test5': 4}
words = ['test1', 'test2', 'test3', 'test4', 'test5']
plot_embeddings(M_reduced_plot_test, word2Ind_plot_test, words)

wprowadź opis zdjęcia tutaj

irudyak
źródło
7

Python 3.6+:

coordinates = [('a',1,2), ('b',3,4), ('c',5,6)]
for x in coordinates: plt.annotate(x[0], (x[1], x[2]))
palash
źródło
2

Jako jeden linijka wykorzystująca funkcję list list i numpy:

[ax.annotate(x[0], (x[1], x[2])) for x in np.array([n,z,y]).T]

konfiguracja jest taka sama jak w przypadku odpowiedzi Rutgera.

andor kesselman
źródło
1

Chciałbym dodać, że możesz nawet używać strzałek / pól tekstowych do opisywania etykiet. Oto co mam na myśli:

import random
import matplotlib.pyplot as plt


y = [2.56422, 3.77284, 3.52623, 3.51468, 3.02199]
z = [0.15, 0.3, 0.45, 0.6, 0.75]
n = [58, 651, 393, 203, 123]

fig, ax = plt.subplots()
ax.scatter(z, y)

ax.annotate(n[0], (z[0], y[0]), xytext=(z[0]+0.05, y[0]+0.3), 
    arrowprops=dict(facecolor='red', shrink=0.05))

ax.annotate(n[1], (z[1], y[1]), xytext=(z[1]-0.05, y[1]-0.3), 
    arrowprops = dict(  arrowstyle="->",
                        connectionstyle="angle3,angleA=0,angleB=-90"))

ax.annotate(n[2], (z[2], y[2]), xytext=(z[2]-0.05, y[2]-0.3), 
    arrowprops = dict(arrowstyle="wedge,tail_width=0.5", alpha=0.1))

ax.annotate(n[3], (z[3], y[3]), xytext=(z[3]+0.05, y[3]-0.2), 
    arrowprops = dict(arrowstyle="fancy"))

ax.annotate(n[4], (z[4], y[4]), xytext=(z[4]-0.1, y[4]-0.2),
    bbox=dict(boxstyle="round", alpha=0.1), 
    arrowprops = dict(arrowstyle="simple"))

plt.show()

Który wygeneruje następujący wykres: wprowadź opis zdjęcia tutaj

Anwarvic
źródło