Seite 1 von 1
[pandas] scatter plot
Verfasst: Donnerstag 13. August 2020, 12:51
von mushroom
Hallo,
habe seit langem Mal wieder mit Python etwas zu tun und versuche Daten aus einem Pandas-DataFrame in einem scatter-plot darzustellen. In gegebenem Beispiel
Code: Alles auswählen
import pandas as pd
df2 = pd.DataFrame(
{"a" : [40700, 40813, 41012],
"b" : [35.1, 32.8, 30.9],
"c" : [1.2, 2.3, 1.9]},
index = [1,2,3])
df2.plot(kind="scatter", x = "a", y = "b")
sind drei Datensätze (Reihen) vorhanden. Mein Problem dabei ist, daß die x-Achse einen Bereich (der die Werte aus Spalte a beinhalten) anzeigt. Gewünscht ist aber ein x-Achse mit drei diskreten Werten (40700, 40813 und 41012).
Habe schon versucht - bei meinem echten Daten - beim read_csv die Spalte a als dtype="{"a":str}" zu formatieren und/oder auch index_col angewandt. Leider läuft alles in Fehlermeldungen aus. Gibt es eine Möglichkeit gewünschtes Problem umzusetzen?
Grüße
Markus
Re: [pandas] scatter plot
Verfasst: Donnerstag 13. August 2020, 13:38
von einfachTobi
Die
Dokumentation von pandas.DataFrame.plot() zeigt, dass es einen Parameter `xticks` gibt, mit dem du diese Werte festlegen kannst.
Re: [pandas] scatter plot
Verfasst: Donnerstag 13. August 2020, 14:14
von mushroom
Hmm, das hilft ein wenig weiter. Allerdings sind die Abstände zwischen den x-Werten nicht äquidistant. Bei meinem realen Datensatz habe ich mehrere Gruppen in weitem Abstand und in den jeweiligen Gruppen kürzere Abstände, ähnlich wie hier:
Code: Alles auswählen
import pandas as pd
df2 = pd.DataFrame(
{"a" : [40700, 40710, 40813, 41012, 41024],
"b" : [35.1, 35.8, 32.8, 33.5, 30.9],
"c" : [1.2, 2.3, 1.9, 1.2, 2.0]},
index = [1,2,3,4,5])
df2.plot(kind="scatter", x = "a", y = "b", xticks=((40700, 40710, 40813, 41012, 41024)))
Re: [pandas] scatter plot
Verfasst: Donnerstag 13. August 2020, 15:22
von __blackjack__
Re: [pandas] scatter plot
Verfasst: Freitag 14. August 2020, 08:44
von mushroom
Hmm, so ganz komme ich mit den FixedLocator auch nicht wieter. Bin mir nicht sicher, ob ich es richtig anwende.
Code: Alles auswählen
import pandas as pd
import matplotlib.ticker as ticker
df2 = pd.DataFrame(
{"a" : [40700, 40710, 40813, 41012, 41024],
"b" : [35.1, 35.8, 32.8, 33.5, 30.9],
"c" : [1.2, 2.3, 1.9, 1.2, 2.0]},
index = [1,2,3,4,5])
df2.plot(kind="scatter", x = "a", y = "b", xticks=((40700, 40710, 40813, 41012, 41024)))
ax = plt.axes()
ax.xaxis.set_major_locator(ticker.FixedLocator([40700,40710,40813,41012,41024]))
df2.plot(kind="scatter", x = "a", y = "b")
Im ersten Bild werden die Ticks zwar richtig zugeordnet, haben aber eben den nicht-äquidistanten Abstand. Im zweiten Bild (FixedLocator angewendet) habe ich zwar konstante Abstände der Ticks aber eine fehlende Zuordnung zu den Datensätzen.
Re: [pandas] scatter plot
Verfasst: Freitag 14. August 2020, 09:48
von __blackjack__
@mushroom: Das ist kein lauffähiges Beispiel. Davon abgesehen, dass `plt` aus dem Nichts kommt, fehlen die `plt.show()`-Aufrufe, damit man mal was sieht. Wenn man die einbaut, sieht man, dass das zu *drei* Plots führt, weil bei Fall zwei einmal mit `ax` ein Plot erstellt wird und dann noch mal einer durch das `df2.plot()`, und die beiden haben nichts miteinander zu tun.
Beim ersten der beiden Plots werden in Fall 2 nur die Ticks an die festen Positionen gesetzt, aber keine Daten geplottet. Die X-Achse scheint leer zu sein, weil ohne Daten der Bereich 0,0 bis 1,0 dargestellt wird, und die festen Tickpositionen *weit* ausserhalb davon liegen.
Wenn man dem ``df2.plot(…)`` das erzeugte `ax` übergibt, damit *da* drauf die Daten geplottet werden, bekomme ich aber das gleiche Bild wie im ersten Fall, wo ich mich dann jetzt frage was Du eigentlich haben willst wenn nicht das, oder ob Du da was anderes bekommst als ich.
Kann es sein das Spalte "a" gar keine X-Werte enthalten soll, sondern das das numerische Kategorien sind, also nur die Beschriftung der X-Ticks? Dann musst Du als X-Werte irgendwas ”künstliches”, schon gleichmässiges nehmen. Also einfach ein entsprechendes `range()`-Objekt oder in diesem Fall den Index von dem DataFrame. Und für die Beschriftung der Ticks dann Spalte "a". Die sollte man auch nicht kopiert in Quelltext stehen haben. Die Werte hat man doch bereits in `df2`.
Re: [pandas] scatter plot
Verfasst: Freitag 14. August 2020, 10:21
von mushroom
Hallo blackjack,
sorry hatte den Codeteil aus mein Jupyter-Notebook rauskopiert und dabei die eine Importanweisung vergessen.
Tatsächlich trifft dein letzter Absatz die Problembeschreibung ganz gut. Wie kann ich denn df2.plot(...) mitteilen, daß er den index als x-Achse benutzen soll? Habe es mit ... x = df2.index probiert
Code: Alles auswählen
import pandas as pd
df2 = pd.DataFrame(
{"a" : [40700, 40710, 40813, 41012, 41024],
"b" : [35.1, 35.8, 32.8, 33.5, 30.9],
"c" : [1.2, 2.3, 1.9, 1.2, 2.0]},
index = [1,2,3,4,5])
df2.plot(kind="scatter", x = df2.index, y = "b", xticks=((40700, 40710, 40813, 41012, 41024)))
erhalte aber die Fehlermeldung
Code: Alles auswählen
KeyError: "None of [Int64Index([1, 2, 3, 4, 5], dtype='int64')] are in the [columns]"
Die xticks würde ich mir bei meinem realen Beispiel natürlich aus dem df2 holen, habe es hier nur quick and dirty gemacht.
Re: [pandas] scatter plot
Verfasst: Freitag 14. August 2020, 11:08
von __blackjack__
Nimm mal ``df2.index.values`` für `x`.
Re: [pandas] scatter plot
Verfasst: Freitag 14. August 2020, 11:25
von mushroom
Liefert leider immer noch denselben Fehler.
Re: [pandas] scatter plot
Verfasst: Freitag 14. August 2020, 12:43
von Sirius3
Was hast Du denn nun versucht?
Re: [pandas] scatter plot
Verfasst: Freitag 14. August 2020, 13:36
von mushroom
Hatte den Hinweis wie folgt verstanden:
Code: Alles auswählen
import pandas as pd
df2 = pd.DataFrame(
{"a" : [40700, 40710, 40813, 41012, 41024],
"b" : [35.1, 35.8, 32.8, 33.5, 30.9],
"c" : [1.2, 2.3, 1.9, 1.2, 2.0]},
index = [1,2,3,4,5])
df2.plot(kind="scatter", x = df2.index.values, y = "b", xticks=((40700, 40710, 40813, 41012, 41024)))
also df2.index durch df2.index.values ersetzt. Will damit die x-Achseneinteilung durch den Index vornehmen und die Ticks dann durch Werte in Spalte "a" setzen.
Re: [pandas] scatter plot
Verfasst: Freitag 14. August 2020, 13:39
von Sirius3
Und das soll den selben Fehler liefern? Bei mir kommt da ein ganz anderer.
Re: [pandas] scatter plot
Verfasst: Montag 17. August 2020, 07:08
von mushroom
Kurioserweise ja, obwohl print(df2.index.values) und print(df2.index) unterschiedliche Ergebnisse liefern. Komplettes traceback:
Code: Alles auswählen
KeyError Traceback (most recent call last)
<ipython-input-3-7707213faada> in <module>
7 index = [1,2,3,4,5])
8
----> 9 df2.plot(kind="scatter", x = df2.index.values, y = "b", xticks=((40700, 40710, 40813, 41012, 41024)))
10
11 #ax = plt.axes()
C:\ProgramData\Anaconda3\lib\site-packages\pandas\plotting\_core.py in __call__(self, *args, **kwargs)
736 if kind in self._dataframe_kinds:
737 if isinstance(data, ABCDataFrame):
--> 738 return plot_backend.plot(data, x=x, y=y, kind=kind, **kwargs)
739 else:
740 raise ValueError(
C:\ProgramData\Anaconda3\lib\site-packages\pandas\plotting\_matplotlib\__init__.py in plot(data, kind, **kwargs)
59 ax = plt.gca()
60 kwargs["ax"] = getattr(ax, "left_ax", ax)
---> 61 plot_obj = PLOT_CLASSES[kind](data, **kwargs)
62 plot_obj.generate()
63 plot_obj.draw()
C:\ProgramData\Anaconda3\lib\site-packages\pandas\plotting\_matplotlib\core.py in __init__(self, data, x, y, s, c, **kwargs)
928 # the handling of this argument later
929 s = 20
--> 930 super().__init__(data, x, y, s=s, **kwargs)
931 if is_integer(c) and not self.data.columns.holds_integer():
932 c = self.data.columns[c]
C:\ProgramData\Anaconda3\lib\site-packages\pandas\plotting\_matplotlib\core.py in __init__(self, data, x, y, **kwargs)
867 if is_integer(y) and not self.data.columns.holds_integer():
868 y = self.data.columns[y]
--> 869 if len(self.data[x]._get_numeric_data()) == 0:
870 raise ValueError(self._kind + " requires x column to be numeric")
871 if len(self.data[y]._get_numeric_data()) == 0:
C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\frame.py in __getitem__(self, key)
2984 if is_iterator(key):
2985 key = list(key)
-> 2986 indexer = self.loc._convert_to_indexer(key, axis=1, raise_missing=True)
2987
2988 # take() does not accept boolean indexers
C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexing.py in _convert_to_indexer(self, obj, axis, is_setter, raise_missing)
1283 # When setting, missing keys are not allowed, even with .loc:
1284 kwargs = {"raise_missing": True if is_setter else raise_missing}
-> 1285 return self._get_listlike_indexer(obj, axis, **kwargs)[1]
1286 else:
1287 try:
C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexing.py in _get_listlike_indexer(self, key, axis, raise_missing)
1090
1091 self._validate_read_indexer(
-> 1092 keyarr, indexer, o._get_axis_number(axis), raise_missing=raise_missing
1093 )
1094 return keyarr, indexer
C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\indexing.py in _validate_read_indexer(self, key, indexer, axis, raise_missing)
1175 raise KeyError(
1176 "None of [{key}] are in the [{axis}]".format(
-> 1177 key=key, axis=self.obj._get_axis_name(axis)
1178 )
1179 )
KeyError: "None of [Int64Index([1, 2, 3, 4, 5], dtype='int64')] are in the [columns]"
Welchen Fehler erhälst du?
Re: [pandas] scatter plot
Verfasst: Montag 17. August 2020, 07:28
von Sirius3
Genau, scatter erwartet die Namen der Spalten. Wenn du etwas anderes willst, musst du matplotlib direkt benutzen.
Re: [pandas] scatter plot
Verfasst: Montag 17. August 2020, 11:46
von mushroom
Hallo,
habe es jetzt direkt in matplotlib gemacht. Der Vollständigkeit halber:
Code: Alles auswählen
import pandas as pd
import matplotlib.pyplot as plt
df2 = pd.DataFrame(
{"a" : [40700, 40710, 40813, 41012, 41024],
"b" : [35.1, 35.8, 32.8, 33.5, 30.9],
"c" : [1.2, 2.3, 1.9, 1.2, 2.0]},
index = [1,2,3,4,5])
plt.scatter(df2.index.values, df2.iloc[:,1])
plt.xticks(df2.index.values,df2.iloc[:,0])
plt.show()
Vielen Dank für eure Hilfe.
Re: [pandas] scatter plot
Verfasst: Montag 17. August 2020, 12:21
von Sirius3
Statt iloc darfst du aber weiterhin über die Spaltennamen zugreifen.