Ich sehe ein seltsames Verhalten bei der automatischen Kennzeichnung der X-Achse für Datumsangaben in Matplotlib. Wenn ich den Befehl:
ausstelle %Vor%Ich bekomme das sehr vernünftig beschriftete Diagramm:
Aber wenn ich das Enddatum um 1 Tag verlängere:
%Vor%Ich verstehe das:
Ich habe dies in verschiedenen Kalenderzeiträumen (im Jahr 2012) reproduziert, und jedes Mal, wenn die magische Anzahl von Tagen benötigt wird, um den Fehler auszulösen, sind es etwa 140 (in diesem Fall 136/137). Wer weiß, was hier vor sich geht? Ist dies ein bekannter Fehler, und wenn ja, gibt es einen Workaround?
Ein paar Anmerkungen: In den obigen Befehlen verwende ich IPython im --pylab-Modus, um die Plots zu erstellen, aber ich habe dieses Problem zuerst direkt mit matplotlib festgestellt und es ist in Skriptform reproduzierbar (dh ich tue es nicht denke, das ist ein IPython-Problem). Auch das habe ich in Matplotlib 1.1.0 und 1.2.X beobachtet.
UPDATE:
Es sieht so aus, als gäbe es ein Fenster, in dem, wenn Sie weit genug nach vorne drücken, sich die Etiketten wieder normal verhalten. Im obigen Beispiel bleiben die Beschriftungen vom 18. Mai bis zum 31. Mai verstümmelt, aber am 1. Juni beginnen die Beschriftungen wieder normal zu zeichnen. Also,
%Vor% Es wurde durch einen Fehler in AutoDateLocator
verursacht. Es scheint, dass dieser Fehler noch nicht im Issue Tracker gemeldet wurde.
Es sieht nur komisch aus, weil zu viele Labels und Ticks geplottet wurden.
Beim Plotten mit Daten mit Datumsangaben verwendet matplotlib standardmäßig matplotlib.dates.AutoDateLocator
als Haupt-Locator. Nämlich, AutoDateLocator
wird verwendet, um das Tick-Intervall und die Tick-Positionen zu bestimmen.
Angenommen, die Datensequenz wird durch [datetime(2013, 1, 1), datetime(2013, 5, 18)]
angegeben.
Das Zeitdelta beträgt 4 Monate und 17 Tage. Das Monatsdelta ist 4 und das Tagesdelta ist 4 * 31 + 17 = 141.
Nach matplotlib docs :
Klasse matplotlib.dates.AutoDateLocator (tz = Keine, minticks = 5, maxticks = Keine, interval_multiples = False)
minticks ist die minimale Anzahl der gewünschten Ticks, die zur Auswahl des Tickingtyps (jährlich, monatlich, etc.) verwendet wird.
maxticks ist die maximale Anzahl der gewünschten Ticks, die jedes Intervall zwischen Ticks steuert (alle anderen Ticks, alle 3 usw.). Für eine wirklich feinkörnige Kontrolle kann dies ein Wörterbuch sein, das individuelle Rulle-Häufigkeitskonstanten (YEARLY, MONTHLY usw.) auf ihre eigene maximale Anzahl von Ticks abbildet. Dies kann verwendet werden, um die Anzahl der Ticks beizubehalten, die für das in der Klasse gewählte Format geeignet sind: AutoDateFormatter. Jede Frequenz, die nicht in diesem Wörterbuch angegeben ist, erhält einen Standardwert.
Der AutoDateLocator verfügt über ein Intervallwörterbuch, das die Häufigkeit des Ticks (eine Konstante aus dateutil.rulle) und ein für dieses Ticking zulässiges Vielfaches abbildet. Der Standard sieht folgendermaßen aus:
%Vor%Das Intervall wird verwendet, um Vielfache anzugeben, die für die Häufigkeit des Tickens geeignet sind. Zum Beispiel ist alle 7 Tage für tägliche Zecken sinnvoll, aber für Minuten / Sekunden sind 15 oder 30 sinnvoll. Sie können dieses Wörterbuch anpassen, indem Sie Folgendes tun:
Da das Monatsdelta 4 ist, weniger als 5, und das Tagesdelta ist 141, nicht weniger als 5. Die Art des Tickens wird täglich sein.
Nach dem Auflösen des Ticking-Typs verwendet AutoDateLocator
das Intervallwörterbuch und das Maxticks-Wörterbuch, um das Tick-Intervall zu bestimmen.
Wenn maxticks
% None
ist, verwendet AutoDateLocator
das Standardmaxticks-Wörterbuch.
Die Dokumentation zeigt uns das Standard-Intervall-Wörterbuch und sagt uns nicht, wie das Standard-Maxticks-Wörterbuch aussieht.
Wir finden es in dates.py .
Der Algorithmus zur Bestimmung des Tick-Intervalls ist
%Vor% Die Art des Tickens ist jetzt DAILY
. Also freq
ist DAILY
und num
ist 141, das Tages-Delta. Der obige Code entspricht
141 ist zu groß. Alle täglichen Intervalle geben zu viele Ticks. else
-Klausel wird ausgeführt und das Tick-Intervall wird auf 1 gesetzt.
Es bedeutet, dass mehr als 140 Etiketten und Zecken gedruckt werden. Wir können eine hässliche X-Achse erwarten.
Wenn die Datensequenz durch [datetime(2013, 1, 1), datetime(2013, 5, 17)]
gegeben ist, nur einen Tag kürzer. Das Tagesdelta ist 140.
Dann wählt AutoDateLocator
14 als Tick-Intervall und nur 10 Labels werden geplottet.
So sieht Ihre erste Grafik gut aus.
Eigentlich verstehe ich nicht, warum matplotlib das Intervall auf 1 setzt, wenn maxticks
constraint nicht erfüllt werden kann.
Es wird nur eine viel größere Anzahl von Ticks ergeben, wenn das Intervall 1 ist. Ich bevorzuge das längste Intervall.
SCHLUSSFOLGERUNG:
Bei einer beliebigen Datumssequenz, deren Bereich größer oder gleich 4 Monaten und 18 Tagen und weniger als 5 Monaten ist, wählt AutoDateLocator
1 als Tick-Intervall.
Sie werden ein hässliches Verhalten auf der X-Achse oder der Y-Achse sehen, wenn Sie eine solche Datumssequenz mit dem Standard-Haupt-Locator, nämlich AutoDateLocator
, plotten.
LÖSUNG:
Die einfachste Lösung besteht darin, die täglichen Maxticks auf 12 zu erhöhen.
Zum Beispiel:
Es fühlt sich an wie ein Käfer; Ich würde es in die Mailplotlib-Mailingliste aufnehmen und sehen, was die Leute dazu sagen können.
Eine Problemumgehung, die ich bereitstellen kann, ist die folgende:
%Vor% Entschuldigung für den OO-Ansatz (was Sie nicht gemacht haben), aber das macht es viel einfacher, die Ticks mit dem Plot zu verknüpfen.
Die Zahl 6
ist genau die Anzahl der Etiketten, die ich entlang der x-Achse haben möchte, und dann reduziere ich die tatsächliche Anzahl der Ticks, die matplotlib ergeben hat, um die berechnete n
.
Tags und Links python datetime matplotlib plot