Ich möchte den Mittelpunkt einer Farbkarte festlegen, dh meine Daten gehen von -5 bis 10, ich möchte, dass Null der Mittelpunkt ist. Ich denke, der Weg, dies zu tun, besteht darin, normalisieren und die Norm zu verwenden, aber ich habe kein Beispiel gefunden und es ist mir nicht klar, was genau ich implementieren muss.
python
matplotlib
Tillsten
quelle
quelle
Antworten:
Beachten Sie, dass in matplotlib Version 3.1 die DivergingNorm- Klasse hinzugefügt wurde. Ich denke, es deckt Ihren Anwendungsfall ab. Es kann folgendermaßen verwendet werden:
In matplotlib 3.2 wurde die Klasse in TwoSlopesNorm umbenannt
quelle
norm
macht die Normalisierung für Ihr Bild.norms
Gehen Sie Hand in Hand mit Farbkarten.TwoSlopeNorm
: matplotlib.org/3.2.0/api/_as_gen/…Ich weiß, dass dies zu spät zum Spiel kommt, aber ich habe gerade diesen Prozess durchlaufen und eine Lösung gefunden, die vielleicht weniger robust als die Normalisierung von Unterklassen ist, aber viel einfacher. Ich dachte, es wäre gut, es hier für die Nachwelt zu teilen.
Die Funktion
Ein Beispiel
Ergebnisse des Beispiels:
quelle
start
undstop
nicht 0 bzw. 1 sind,reg_index = np.linspace(start, stop, 257)
können Sie danach nicht mehr davon ausgehen, dass der Wert 129 der Mittelpunkt der ursprünglichen cmap ist. Daher macht die gesamte Neuskalierung beim Zuschneiden keinen Sinn. Solltestart
auch von 0 bis 0,5 undstop
von 0,5 bis 1 sein, nicht beide von 0 bis 1, wie Sie anweisen.midpoint
Daten gleich 0 oder 1 sind. Eine einfache Lösung für dieses Problem finden Sie in meiner Antwort unten.Hier ist eine Lösungsunterklasse Normalisieren. Um es zu benutzen
Hier ist die Klasse:
quelle
Es ist am einfachsten, nur die Argumente
vmin
und zuvmax
zu verwendenimshow
(vorausgesetzt, Sie arbeiten mit Bilddaten), anstatt eine Unterklasse zu erstellenmatplotlib.colors.Normalize
.Z.B
quelle
Normalize
. Ich werde gleich ein Beispiel hinzufügen (vorausgesetzt, jemand anderes schlägt mich nicht ...).vmax=abs(Z).max(), vmin=-abs(Z).max()
Diese Lösung wurde von einer gleichnamigen Klasse auf dieser Seite inspiriert
Hier erstelle ich eine Unterklasse von
Normalize
gefolgt von einem minimalen Beispiel.Ergebnis:
Und das gleiche Beispiel mit nur positiven Daten
vals = sp.array([[1., 3], [6, 10]])
Um es zusammenzufassen - diese Norm hat folgende Eigenschaften:
vmin
es größer als istmidpoint
(es wurden jedoch nicht alle Randfälle getestet).quelle
def __call__
)normalized_min
undnormalized_max
werden als ganze Zahlen genommen. Setzen Sie sie einfach als 0.0. Um die korrekte Ausgabe Ihrer Figur zu erhalten, musste ich auch verwendenvals = sp.array([[-5.0, 0.0], [5.0, 10.0]])
. Trotzdem danke für die Antwort!Ich bin mir nicht sicher, ob Sie noch nach einer Antwort suchen. Für mich war der Versuch, eine Unterklasse zu erstellen,
Normalize
erfolglos. Daher habe ich mich darauf konzentriert, manuell einen neuen Datensatz, Ticks und Tick-Labels zu erstellen, um den Effekt zu erzielen, den Sie meiner Meinung nach anstreben.Ich habe das
scale
Modul in matplotlib gefunden, das eine Klasse hat, die zum Transformieren von Liniendiagrammen nach den 'syslog'-Regeln verwendet wird, also verwende ich das, um die Daten zu transformieren. Dann skaliere ich die Daten so, dass sie von 0 auf 1 gehen (wasNormalize
normalerweise der Fall ist), aber ich skaliere die positiven Zahlen anders als die negativen Zahlen. Dies liegt daran, dass Ihr vmax und Ihr vmin möglicherweise nicht identisch sind. Daher deckt .5 -> 1 möglicherweise einen größeren positiven Bereich ab als .5 -> 0, der negative Bereich jedoch. Es war für mich einfacher, eine Routine zur Berechnung der Tick- und Label-Werte zu erstellen.Unten finden Sie den Code und eine Beispielabbildung.
Sie können die "Konstanten" (z. B.
VMAX
) oben im Skript anpassen, um zu bestätigen, dass es sich gut verhält.quelle
Ich habe die ausgezeichnete Antwort von Paul H verwendet, bin jedoch auf ein Problem gestoßen, da einige meiner Daten von negativ bis positiv reichten, während andere Sätze von 0 bis positiv oder von negativ bis 0 reichten. In beiden Fällen wollte ich, dass 0 weiß gefärbt wird (der Mittelpunkt der von mir verwendeten Farbkarte). Wenn bei der vorhandenen Implementierung Ihr
midpoint
Wert gleich 1 oder 0 ist, wurden die ursprünglichen Zuordnungen nicht überschrieben. Sie können dies auf dem folgenden Bild sehen: Die 3. Spalte sieht korrekt aus, aber der dunkelblaue Bereich in der 2. Spalte und der dunkelrote Bereich in den verbleibenden Spalten sollten alle weiß sein (ihre Datenwerte sind tatsächlich 0). Die Verwendung meines Fixes gibt mir Folgendes: Meine Funktion ist im Wesentlichen dieselbe wie die von Paul H, mit meinen Änderungen am Anfang derfor
Schleife:BEARBEITEN: Ich bin erneut auf ein ähnliches Problem gestoßen, als einige meiner Daten von einem kleinen positiven Wert zu einem größeren positiven Wert reichten, bei dem die sehr niedrigen Werte rot statt weiß gefärbt wurden. Ich habe es behoben, indem ich
Edit #2
im obigen Code eine Zeile hinzugefügt habe .quelle
Wenn es Ihnen nichts ausmacht, das Verhältnis zwischen vmin, vmax und Null zu berechnen, ist dies eine ziemlich einfache lineare Karte von blau über weiß nach rot, die Weiß entsprechend dem Verhältnis festlegt
z
:Das cdict-Format ist ziemlich einfach: Die Zeilen sind Punkte in dem Verlauf, der erstellt wird: Der erste Eintrag ist der x-Wert (das Verhältnis entlang des Verlaufs von 0 zu 1), der zweite ist der Endwert für das vorherige Segment und Der dritte ist der Startwert für das nächste Segment. Wenn Sie glatte Verläufe wünschen, sind die beiden letzteren immer gleich. Weitere Informationen finden Sie in den Dokumenten .
quelle
LinearSegmentedColormap.from_list()
Tupel anzugeben(val,color)
und diese als Liste an dascolor
Argument dieser Methode zu übergeben, wobeival0=0<val1<...<valN==1
.Ich hatte ein ähnliches Problem, aber ich wollte, dass der höchste Wert voll rot ist und niedrige Blauwerte abgeschnitten werden, sodass es im Wesentlichen so aussieht, als wäre der Boden der Farbleiste abgeschnitten. Dies hat bei mir funktioniert (einschließlich optionaler Transparenz):
quelle