matplotlib: Jahreszahlen auf X-Achse

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
zegru
User
Beiträge: 21
Registriert: Freitag 9. Oktober 2020, 09:22

Sonntag 8. November 2020, 17:35

Hallo!

Ich habe ein Problem: Bei diesem Beispiel sind die Werte auf der X-Achse Jahre. Sie sollten als ganze Zahlen und nicht beispielsweise "2007.5" dargestellt werden. Wie kann ich das erreichen?

Code: Alles auswählen

import matplotlib.pyplot as plt

X = range(1991, 2011+1)
Y = [1 for year in X]

plt.plot(X, Y)
plt.show()
narpfel
User
Beiträge: 296
Registriert: Freitag 20. Oktober 2017, 16:10

Sonntag 8. November 2020, 19:09

Moin,

dafür kannst du entweder `YearLocator` nehmen, wenn du `datetime`-Objekte aus deinen x-Werten machst; oder du baust das mit `matplotlib.ticker` nach.

`Y` kannst du übrigens einfacher als `[1] * len(X)` definieren.
zegru
User
Beiträge: 21
Registriert: Freitag 9. Oktober 2020, 09:22

Freitag 13. November 2020, 17:01

Danke, das hat funktioniert. Ich habe es so implementiert:

Code: Alles auswählen

...
locator = YearLocator(1)
locator.set_axis(plt.axis)
...
Leider bin ich nicht früher dazu gekommen, dies zu schreiben, weil in dem realen Programm noch so allerlei andere Dinge passieren, die ich auch noch anpassen muss.
zegru
User
Beiträge: 21
Registriert: Freitag 9. Oktober 2020, 09:22

Freitag 13. November 2020, 18:18

Jetzt habe ich ein neues Problem, und zwar bein Erzeugen eines Violin Plots:

Code: Alles auswählen

from datetime import datetime

import matplotlib.pyplot as plt
from matplotlib.dates import YearLocator

X = []
for year in range(1991, 2011+1):
    if year == 2000:  # Ein Jahr Lücke
        continue
    X.append(datetime(day=1, month=1, year=year))
Y = [1] * len(X)

locator = YearLocator(1)
locator.set_axis(plt.axis)

print(f"len Y: {len(Y)}")
print(f"len X: {len(X)}")

plt.violinplot(Y, positions=X)
plt.show()
Es wird mir eine seltsame Fehlermeldung ausgegeben, die ich leider nicht weg bekomme.
Wie kann ich ein violin plot erzeugen?
tonikae
User
Beiträge: 40
Registriert: Sonntag 23. Februar 2020, 10:27

Sonntag 15. November 2020, 15:09

Bei Violinen sind X und Y nicht getrennt..das geht so:

data=[X,Y]
plt.violinplot(data)


In deinem Fall

# guckst du hier
import numpy as np
data=[np.arange(len(X)),Y]
plt.violinplot(data)
plt.show()
zegru
User
Beiträge: 21
Registriert: Freitag 9. Oktober 2020, 09:22

Montag 16. November 2020, 21:55

Ich habe folgendes Stück Code genommen, um damit herumzuspielen (Stochern im Nebel). Leider ohne Erfolg.

Kann mir damit jemand weiterhelfen?

Code: Alles auswählen

from datetime import datetime

import matplotlib.pyplot as plt
from matplotlib.dates import YearLocator
import numpy as np


X_years = range(1991, 2011 + 1)
X = [datetime(day=1, month=1, year=year) for year in X_years]
Y = [1] * len(X)
data = [X_years, Y]  # Auch mit numplot experimentiert

# locator = YearLocator(1)
# locator.set_axis(plt.axis)

print(f"len X: {len(X)}, len Y: {len(Y)}, len X_years: {len(X_years)}")

plt.violinplot(data)  # , positions=X_years)
plt.show()
tonikae
User
Beiträge: 40
Registriert: Sonntag 23. Februar 2020, 10:27

Dienstag 17. November 2020, 11:14

Hier ein Code-Snippet in dem die Anzeige von Violinen etwas
überzeichnet(aber hoffentlich verständlich) dargestellt wird.

Code: Alles auswählen

import matplotlib.pyplot as plt
import numpy as np

figure,ax = plt.subplots()

Jahre = []
for year in range(1991, 1995):
    Jahre.append(year)
ax.set_xticks(np.arange(len(Jahre)))
ax.set_xticklabels(Jahre)

record1=[1,2,3,4,5,6,7,8,9,10]
record2=[2,4,3,7,12,4,1,19,7,5]
record3=[0.3, 0.1, 0.7, 0.1, 0.1, 0.7, 0.9, 1, 3, 0.5]

data=[record1,record2, record3]
plt.violinplot(data)

plt.gcf().autofmt_xdate()
plt.show() 
zegru
User
Beiträge: 21
Registriert: Freitag 9. Oktober 2020, 09:22

Samstag 21. November 2020, 18:49

Ich habe nun diesen Code zum Spielen verwendet:

Code: Alles auswählen

import random
import matplotlib.pyplot as plt
import numpy as np

figure,ax = plt.subplots()

begin = 1991
end = 2011
Jahre = []
data = []
for year in range(begin, end+1):
    if year == 2000:
        continue
    Jahre.append(year)
    data.append(random.sample(range(10, 30), 10))
ax.set_xticks(np.arange(len(Jahre)))
ax.set_xticklabels(Jahre)

plt.violinplot(data)#, positions=Jahre)

plt.gcf().autofmt_xdate()
plt.show() 
Wenn ich das mit den positions wegkommentiert lasse, werden die Jahreszahlen zwar ausgegeben (aber für meinen Geschmack zu viele), aber an der verkehrten Position. Und wenn ich es mit positions mache, werden gar keine ausgegeben. Es ist zum Mäuse melken!
simplesimon
User
Beiträge: 8
Registriert: Samstag 3. Dezember 2016, 21:50

Samstag 21. November 2020, 22:28

Die Jahreszahlen stehen an der richtigen Stelle, wenn die folgende Zeile verwendet wird

Code: Alles auswählen

ax.set_xticks(np.arange(len(Jahre))+1)
zegru
User
Beiträge: 21
Registriert: Freitag 9. Oktober 2020, 09:22

Samstag 21. November 2020, 23:01

Jein. Die einzelnen Spalten tragen zwar nun die korrekte Beschriftung, die treten aber lückenlos auf: In diesem Beispiel ..., 1998, 1999, 2001, 2002, ... Das Jahr 2000 wird buchstäblich spurlos ausgelassen.
simplesimon
User
Beiträge: 8
Registriert: Samstag 3. Dezember 2016, 21:50

Samstag 21. November 2020, 23:53

Im matplotlib-Handbuch steht unter matplotlib.axes.Axes.violinplot:
positions: array-like, default: [1, 2, ..., n]
Sets the positions of the violins. The ticks and limits are automatically set to match the positions.

Bei Verwendung von Positions dürfen daher keine ticks gesetzt werden.

Code: Alles auswählen

import random
import matplotlib.pyplot as plt
import numpy as np

figure,ax = plt.subplots()

begin = 1991
end = 2011
Jahre = []
data = []
for year in range(begin, end+1):
    if year == 2000:
       continue
    Jahre.append(year)
    data.append(random.sample(range(10, 30), 10))

plt.violinplot(data, positions=Jahre)

plt.gcf().autofmt_xdate()
plt.show()
zegru
User
Beiträge: 21
Registriert: Freitag 9. Oktober 2020, 09:22

Sonntag 22. November 2020, 23:05

Das Problem tritt immer noch auf. Ich habe nochmal genauer nachgeschaut, und die Jahre beginnen bei 1992. Hier also ein Minimalbeispiel, bei dem der Fehler trotz aller Bemühungen immer noch auftritt:

Code: Alles auswählen

import random
from matplotlib import pyplot as plt

keys = []
values = []
for year in range(1992, 2011+1):
    if year == 1994:
        continue
    keys.append(year)
    values.append(random.sample(range(10, 30), 3))
print(f"keys: {keys}; type: {type(keys[5])}")
print(f"values: {values}")

#plt.gcf().autofmt_xdate()
plt.violinplot(values, positions=keys)

plt.show()
Ob die Zeile mit xdate auskommentiert ist oder nicht macht übrigens keinen einschneidenden Unterschied.
tonikae
User
Beiträge: 40
Registriert: Sonntag 23. Februar 2020, 10:27

Montag 23. November 2020, 08:01

Gut noch einmal kurz zusammengefasst:
Mit "set_xticks/set_yticks" definiert man die Anzahl der Ticks (also die Anzahl der Einteilungsstriche) auf den Achsen eines Diagramms.
Die Beschriftung der Achsen macht man mit: "set_xtickslabels/set_ytickslabels" und da kann man alles mögliche
eintragen, Werte, Strings, Daten, Uhrzeiten u.s.w. Es ist also problemlos möglich auf den Achsen des Diagramms
3 Einteilungstriche und 15 Beschriftungen festzulegen...oder umgekehrt.
Beides kann man völlig frei festlegen und hat zunächst einmal nichts mit der Anzahl der Violinenplots zu tun.
Die gewünschte Größe eines Diagramms legt man üblicherweise mit: "figsize=(Breite,Höhe)" fest.
Beispiel:
fig, ax = pyplot.subplots(nrows=2, ncols=3, dpi=100, figsize=(16,8))

Zu den Violinenplots.Die haben kein X/Y, wie ein LinienPlot
Die Daten stammen(in dem Code-Snippet) aus einem simulierten Dataset mit 3 Datensätzen (kann auch eine Datenbank, oder CSV o.ä sein),
und nur die Anzahl der Datensätze bestimmt (in dem Code-Snippet) wie vieviele Violinen angezeigt werden
d.h.
wenn du eine z.B eine CSV-Datei mit 10 Datensätzen einliest,und in einer Liste(hier: data) zusammenfasst(wie im Code-Snippet gezeigt) werde eben auch 10 Violinenplots
angezeigt.Wenn du nur jeden zweiten Datensatz haben möchtest,trägst du in die Liste eben nur jede zweiten Datensatz ein u.s.w.. Wenn man das so macht, braucht man
den Positions-Parameter gar nicht. Du kannst es aber auch anders regeln...ganz nach deinen eigenen Vorstellungen.

Hoffe das hat geholfen Unklarheiten zu beseitigen.
Antworten