Grafico a dispersione Matplotlib con testo diverso in ciascun punto dati


252

Sto cercando di creare un diagramma a dispersione e annotare punti dati con numeri diversi da un elenco. Quindi, ad esempio, voglio tracciare yvs xe annotare con i numeri corrispondenti da 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')

Qualche idea?


Puoi anche ottenere un grafico a dispersione con le etichette dei suggerimenti al passaggio del mouse utilizzando la libreria mpld3. mpld3.github.io/examples/scatter_tooltip.html
Claude COULOMBE

Risposte:


466

Non sono a conoscenza di alcun metodo di tracciamento che accetta matrici o elenchi, ma è possibile utilizzarlo annotate()durante l'iterazione dei valori in 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]))

Esistono molte opzioni di formattazione per annotate(), consultare il sito Web matplotlib:

inserisci qui la descrizione dell'immagine


1
Funziona bene anche con Seaborn regplotsenza troppe interruzioni.
ijoseph,

@Rutger Uso un frame di dati Panda e in qualche modo ottengo un KeyError- quindi immagino che dict()ci si aspetta un oggetto? C'è un altro modo per etichettare i dati utilizzando enumerate, annotatee una cornice di panda di dati?
Rachel,

@ Rachel, puoi usare for row in df.iterrows():e quindi accedere ai valori con row['text'], row['x-coord']ecc. Se pubblichi una domanda separata, la guarderò.
Rutger Kassies il

@RutgerKassies Grazie, Rutger! Ho pubblicato una domanda qui stackoverflow.com/questions/41481153/… Temo che potrebbe essere simile a questa domanda. Ma non riesco a risolverlo in qualche modo. Grazie per l'aiuto!
Rachel,

1
@aviatore, purtroppo non integrato. Ma vedi, per esempio motore di layout questo usando del NetworkX: stackoverflow.com/a/34697108/1755432
Rutger Kassies

32

Nella versione precedente a matplotlib 2.0, ax.scatternon è necessario tracciare il testo senza marcatori. Nella versione 2.0 dovrai ax.scatterimpostare l'intervallo e gli indicatori corretti per il testo.

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]))

E in questo link puoi trovare un esempio in 3d.


Questo e spettacolare! Grazie per aver condiviso questa soluzione. Puoi anche condividere qual è il codice corretto per impostare la dimensione della figura? Le implementazioni come plt.figure(figsize=(20,10))non funzionano come previsto, in quanto l'invocazione di questo codice non modifica le dimensioni dell'immagine. In attesa di vostro aiuto. Grazie!
Levine,

fig, ax = plt.subplots (figsize = (20,10))
rafaelvalle

21

Nel caso in cui qualcuno stia provando ad applicare le soluzioni sopra a un .scatter () invece di un .subplot (),

Ho provato a eseguire il seguente codice

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]))

Ma si sono imbattuti in errori affermando "impossibile decomprimere l'oggetto PathCollection non iterabile", con l'errore che punta specificamente alla codeline fig, ax = plt.scatter (z, y)

Alla fine ho risolto l'errore usando il seguente codice

plt.scatter(z, y)

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

Non mi aspettavo che ci fosse una differenza tra .scatter () e .subplot () avrei dovuto conoscerlo meglio.


11

Puoi anche usare pyplot.text(vedi qui ).

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)

inserisci qui la descrizione dell'immagine


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]))

2

Come una fodera usando la comprensione della lista e intorpidimento:

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

l'installazione è idem per la risposta di Rutger.


1

Mi piacerebbe aggiungere che puoi persino usare frecce / caselle di testo per annotare le etichette. Ecco cosa intendo:

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()

Che genererà il seguente grafico: inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.