Matplotlib-Streudiagramm mit unterschiedlichem Text an jedem Datenpunkt

252

Ich versuche, ein Streudiagramm zu erstellen und Datenpunkte mit verschiedenen Nummern aus einer Liste zu versehen. So möchte ich zum Beispiel yvs zeichnen xund mit entsprechenden Zahlen von kommentieren 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')

Irgendwelche Ideen?

Labibah
quelle
Mithilfe der mpld3-Bibliothek können Sie auch Streudiagramme mit QuickInfo-Beschriftungen beim Hover abrufen. mpld3.github.io/examples/scatter_tooltip.html
Claude COULOMBE

Antworten:

466

Mir ist keine Plotmethode bekannt, die Arrays oder Listen verwendet, aber Sie können sie verwenden, annotate()während Sie über die Werte in iterieren 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]))

Es gibt viele Formatierungsoptionen für annotate(), siehe die matplotlib-Website:

Geben Sie hier die Bildbeschreibung ein

Rutger Kassies
quelle
1
Funktioniert auch gut auf Seaborns, regplotohne zu viel zu stören.
Ijoseph
@Rutger Ich benutze einen Pandas-Datenrahmen und bekomme irgendwie einen KeyError- also wird wohl ein dict()Objekt erwartet? Gibt es eine andere Möglichkeit , die Daten unter Verwendung von beschriften enumerate, annotateund Pandas Datenrahmen?
Rachel
@Rachel, Sie können verwenden for row in df.iterrows():und dann mit row['text'], row['x-coord']usw. auf die Werte zugreifen . Wenn Sie eine separate Frage stellen, werde ich sie mir ansehen.
Rutger Kassies
@ RutgerKassies Danke, Rutger! Ich habe hier eine Frage gestellt. Stackoverflow.com/questions/41481153/… Ich befürchte, dass diese Frage zu ähnlich ist. Aber ich kann es irgendwie nicht herausfinden. Danke für Ihre Hilfe!
Rachel
1
@aviator, leider nicht eingebaut. Aber sehen Sie dies zum Beispiel mit der Layout-Engine von networkx
Rutger Kassies
32

In früheren Versionen als matplotlib 2.0 ax.scatterist es nicht erforderlich, Text ohne Markierungen zu zeichnen. In Version 2.0 müssen Sie ax.scatterden richtigen Bereich und die richtigen Markierungen für Text festlegen.

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

Und in diesem Link finden Sie ein Beispiel in 3D.

rafaelvalle
quelle
Das ist fantastisch! Vielen Dank, dass Sie diese Lösung geteilt haben. Können Sie auch mitteilen, wie der richtige Code zum Einstellen der Größe der Figur lautet? Implementierungen wie plt.figure(figsize=(20,10))funktionieren nicht wie erwartet, da das Aufrufen dieses Codes die Größe des Bildes nicht ändert. Ich freue mich auf Ihre Hilfe. Vielen Dank!
Levine
fig, ax = plt.subplots (figsize = (20,10))
rafaelvalle
21

Falls jemand versucht, die oben genannten Lösungen auf eine .scatter () anstelle einer .subplot () anzuwenden,

Ich habe versucht, den folgenden Code auszuführen

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

Es ist jedoch ein Fehler aufgetreten, der besagt, dass ein nicht iterierbares PathCollection-Objekt nicht entpackt werden kann. Der Fehler zeigt speziell auf die Codeline fig, ax = plt.scatter (z, y).

Ich habe den Fehler schließlich mit dem folgenden Code behoben

plt.scatter(z, y)

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

Ich hatte nicht erwartet, dass es einen Unterschied zwischen .scatter () und .subplot () gibt, den ich besser hätte kennen sollen.

Heather Claxton
quelle
11

Sie können auch verwenden pyplot.text(siehe hier ).

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)

Geben Sie hier die Bildbeschreibung ein

irudyak
quelle
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
quelle
2

Als Einzeiler mit Listenverständnis und Numpy:

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

Das Setup ist ebenso wie Rutgers Antwort.

andor kesselman
quelle
1

Ich würde gerne hinzufügen, dass Sie sogar Pfeile / Textfelder verwenden können, um die Beschriftungen zu kommentieren. Folgendes meine ich:

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

Welches wird die folgende Grafik erzeugen: Geben Sie hier die Bildbeschreibung ein

Anwarvic
quelle