Was ist der beste Weg, um eine Reihe von Streudiagrammen mithilfe matplotlib
eines pandas
Datenrahmens in Python zu erstellen?
Wenn ich beispielsweise einen Datenrahmen df
mit einigen interessanten Spalten habe, konvertiere ich normalerweise alles in Arrays:
import matplotlib.pylab as plt
# df is a DataFrame: fetch col1 and col2
# and drop na rows if any of the columns are NA
mydata = df[["col1", "col2"]].dropna(how="any")
# Now plot with matplotlib
vals = mydata.values
plt.scatter(vals[:, 0], vals[:, 1])
Das Problem beim Konvertieren von allem in ein Array vor dem Plotten besteht darin, dass Sie gezwungen sind, aus Datenrahmen auszubrechen.
Betrachten Sie diese beiden Anwendungsfälle, in denen der vollständige Datenrahmen für das Plotten unerlässlich ist:
Was wäre zum Beispiel, wenn Sie jetzt alle Werte
col3
für die entsprechenden Werte anzeigen möchten, die Sie im Aufruf gezeichnet habenscatter
, und jeden Punkt (oder jede Größe) mit diesem Wert färben möchten? Sie müssten zurückgehen, die Nicht-Na-Werte von herausziehen und diecol1,col2
entsprechenden Werte überprüfen.Gibt es eine Möglichkeit zum Plotten unter Beibehaltung des Datenrahmens? Zum Beispiel:
mydata = df.dropna(how="any", subset=["col1", "col2"]) # plot a scatter of col1 by col2, with sizes according to col3 scatter(mydata(["col1", "col2"]), s=mydata["col3"])
Stellen Sie sich vor, Sie möchten jeden Punkt abhängig von den Werten einiger Spalten unterschiedlich filtern oder färben. Was wäre beispielsweise, wenn Sie die Beschriftungen der Punkte, die einen bestimmten Grenzwert treffen, automatisch neben sich zeichnen
col1, col2
möchten (wobei die Beschriftungen in einer anderen Spalte des df gespeichert sind) oder diese Punkte anders färben möchten, wie dies bei Datenrahmen in R der Fall ist Beispiel:mydata = df.dropna(how="any", subset=["col1", "col2"]) myscatter = scatter(mydata[["col1", "col2"]], s=1) # Plot in red, with smaller size, all the points that # have a col2 value greater than 0.5 myscatter.replot(mydata["col2"] > 0.5, color="red", s=0.5)
Wie kann das gemacht werden?
EDIT Antwort crewbum:
Sie sagen, dass der beste Weg ist, jede Bedingung (wie subset_a
, subset_b
) separat zu zeichnen . Was ist, wenn Sie viele Bedingungen haben, z. B. wenn Sie die Streuungen in 4 Arten von Punkten oder sogar mehr aufteilen möchten, wobei Sie jede in unterschiedlicher Form / Farbe zeichnen möchten. Wie können Sie die Bedingungen a, b, c usw. elegant anwenden und sicherstellen, dass Sie als letzten Schritt "den Rest" (Dinge, die in keiner dieser Bedingungen enthalten sind) zeichnen?
Ähnlich verhält es sich in Ihrem Beispiel, in dem Sie je nach Darstellung col1,col2
unterschiedlich darstellen, mit col3
NA-Werten, die die Zuordnung zwischen diesen Werten aufheben col1,col2,col3
? Zum Beispiel, wenn Sie alle col2
Werte basierend auf ihren col3
Werten zeichnen möchten , aber einige Zeilen einen NA-Wert in entweder col1
oder haben col3
, was Sie dazu zwingt, zuerst zu verwenden dropna
. Also würden Sie tun:
mydata = df.dropna(how="any", subset=["col1", "col2", "col3")
Dann können Sie mit mydata
wie gezeigt zeichnen - die Streuung zwischen col1,col2
den Werten von col3
. Es mydata
fehlen jedoch einige Punkte, für die Werte col1,col2
vorliegen col3
, für die jedoch NA angegeben sind , und die noch gezeichnet werden müssen. Wie würden Sie also im Grunde "den Rest" der Daten darstellen, dh die Punkte, die nicht in der gefilterten Menge enthalten sind mydata
?
Antworten:
Versuchen Sie, Spalten der
DataFrame
direkt an matplotlib zu übergeben, wie in den folgenden Beispielen, anstatt sie als numpy-Arrays zu extrahieren.df = pd.DataFrame(np.random.randn(10,2), columns=['col1','col2']) df['col3'] = np.arange(len(df))**2 * 100 + 100 In [5]: df Out[5]: col1 col2 col3 0 -1.000075 -0.759910 100 1 0.510382 0.972615 200 2 1.872067 -0.731010 500 3 0.131612 1.075142 1000 4 1.497820 0.237024 1700
Variieren Sie die Streupunktgröße basierend auf einer anderen Spalte
plt.scatter(df.col1, df.col2, s=df.col3) # OR (with pandas 0.13 and up) df.plot(kind='scatter', x='col1', y='col2', s=df.col3)
Variieren Sie die Streupunktfarbe basierend auf einer anderen Spalte
colors = np.where(df.col3 > 300, 'r', 'k') plt.scatter(df.col1, df.col2, s=120, c=colors) # OR (with pandas 0.13 and up) df.plot(kind='scatter', x='col1', y='col2', s=120, c=colors)
Streudiagramm mit Legende
Der einfachste Weg, ein Streudiagramm mit Legende zu erstellen, besteht darin,
plt.scatter
für jeden Punkttyp einmal aufzurufen .cond = df.col3 > 300 subset_a = df[cond].dropna() subset_b = df[~cond].dropna() plt.scatter(subset_a.col1, subset_a.col2, s=120, c='b', label='col3 > 300') plt.scatter(subset_b.col1, subset_b.col2, s=60, c='r', label='col3 <= 300') plt.legend()
Aktualisieren
Nach allem, was ich sagen kann, überspringt matplotlib einfach Punkte mit NA x / y-Koordinaten oder NA-Stileinstellungen (z. B. Farbe / Größe). Versuchen Sie die folgende
isnull
Methode , um aufgrund von NA übersprungene Punkte zu finden :df[df.col3.isnull()]
Um eine Liste von Punkten in viele Typen aufzuteilen
select
, werfen Sie einen Blick auf numpy , eine vektorisierte Wenn-Dann-Sonst-Implementierung, die einen optionalen Standardwert akzeptiert. Zum Beispiel:df['subset'] = np.select([df.col3 < 150, df.col3 < 400, df.col3 < 600], [0, 1, 2], -1) for color, label in zip('bgrm', [0, 1, 2, -1]): subset = df[df.subset == label] plt.scatter(subset.col1, subset.col2, s=120, c=color, label=str(label)) plt.legend()
quelle
Garretts großartiger Antwort kann wenig hinzugefügt werden, aber Pandas haben auch eine
scatter
Methode . Damit ist es so einfach wiedf = pd.DataFrame(np.random.randn(10,2), columns=['col1','col2']) df['col3'] = np.arange(len(df))**2 * 100 + 100 df.plot.scatter('col1', 'col2', df['col3'])
quelle
Ich werde empfehlen, eine alternative Methode zu verwenden, mit der
seaborn
das leistungsstärkere Tool zum Zeichnen von Daten verwendet wird. Sie könnenseaborn scatterplot
Spalte 3 alshue
und verwenden und definierensize
.Arbeitscode:
import pandas as pd import seaborn as sns import numpy as np #creating sample data sample_data={'col_name_1':np.random.rand(20), 'col_name_2': np.random.rand(20),'col_name_3': np.arange(20)*100} df= pd.DataFrame(sample_data) sns.scatterplot(x="col_name_1", y="col_name_2", data=df, hue="col_name_3",size="col_name_3")
quelle