Hinweis
Zum Ende springen, um den vollständigen Beispielcode herunterzuladen.
Auswahl von Colormaps in Matplotlib#
Matplotlib verfügt über eine Reihe integrierter Colormaps, die über matplotlib.colormaps zugänglich sind. Es gibt auch externe Bibliotheken, die viele zusätzliche Colormaps enthalten, die im Abschnitt Drittanbieter-Colormaps der Matplotlib-Dokumentation eingesehen werden können. Hier besprechen wir kurz, wie man zwischen den vielen Optionen wählt. Hilfe zur Erstellung eigener Colormaps finden Sie unter Erstellung von Colormaps in Matplotlib.
Um eine Liste aller registrierten Colormaps zu erhalten, können Sie
from matplotlib import colormaps
list(colormaps)
Übersicht#
Die Idee hinter der Auswahl einer guten Colormap ist, eine gute Darstellung Ihres Datensatzes im 3D-Farbraum zu finden. Die beste Colormap für einen bestimmten Datensatz hängt von vielen Faktoren ab, darunter
Ob Form- oder metrische Daten dargestellt werden ([Ware])
Ihr Wissen über den Datensatz (z. B., gibt es einen kritischen Wert, von dem die anderen Werte abweichen?)
Ob es ein intuitives Farbschema für den dargestellten Parameter gibt
Ob es in der Branche einen Standard gibt, den das Publikum erwartet
Für viele Anwendungen ist eine wahrnehmungsuniforme Colormap die beste Wahl; d.h. eine Colormap, bei der gleiche Datenschritte als gleiche Schritte im Farbraum wahrgenommen werden. Forscher haben festgestellt, dass das menschliche Gehirn Änderungen im Helligkeitsparameter viel besser als Änderungen in der Datenwahrnehmung wahrnimmt als beispielsweise Änderungen im Farbton. Daher werden Colormaps, bei denen die Helligkeit durchgehend monoton ansteigt, vom Betrachter besser interpretiert. Wunderbare Beispiele für wahrnehmungsuniforme Colormaps finden Sie auch im Abschnitt Drittanbieter-Colormaps.
Farbe kann auf verschiedene Weise im 3D-Raum dargestellt werden. Eine Möglichkeit, Farbe darzustellen, ist die Verwendung von CIELAB. In CIELAB wird der Farbraum durch Helligkeit, \(L^*\); Rot-Grün, \(a^*\); und Gelb-Blau, \(b^*\) dargestellt. Der Helligkeitsparameter \(L^*\) kann dann verwendet werden, um mehr darüber zu erfahren, wie die Matplotlib-Colormaps von den Betrachtern wahrgenommen werden.
Eine ausgezeichnete erste Ressource zum Erlernen der menschlichen Wahrnehmung von Colormaps ist von [IBM].
Klassen von Colormaps#
Colormaps werden oft nach ihrer Funktion in mehrere Kategorien eingeteilt (siehe z.B. [Moreland])
Sequentiell: Erhöht inkrementell Helligkeit und oft Sättigung der Farbe, oft unter Verwendung eines einzigen Farbtons; sollte zur Darstellung von Informationen mit Reihenfolge verwendet werden.
Divergierend: Ändert Helligkeit und möglicherweise Sättigung zweier verschiedener Farben, die sich in der Mitte bei einer ungesättigten Farbe treffen; sollte verwendet werden, wenn die dargestellten Informationen einen kritischen Mittelwert haben, wie z. B. Topografie oder wenn die Daten um Null abweichen.
Zyklisch: Ändert Helligkeit zweier verschiedener Farben, die sich in der Mitte treffen und am Anfang/Ende eine ungesättigte Farbe haben; sollte für Werte verwendet werden, die an den Endpunkten umbrechen, wie z. B. Phasenwinkel, Windrichtung oder Tageszeit.
Qualitativ: Oft verschiedene Farben; sollte zur Darstellung von Informationen verwendet werden, die keine Reihenfolge oder Beziehungen haben.
from colorspacious import cspace_converter
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
Zuerst zeigen wir den Bereich jeder Colormap. Beachten Sie, dass einige "schneller" zu wechseln scheinen als andere.
cmaps = {}
gradient = np.linspace(0, 1, 256)
gradient = np.vstack((gradient, gradient))
def plot_color_gradients(category, cmap_list):
# Create figure and adjust figure height to number of colormaps
nrows = len(cmap_list)
figh = 0.35 + 0.15 + (nrows + (nrows - 1) * 0.1) * 0.22
fig, axs = plt.subplots(nrows=nrows + 1, figsize=(6.4, figh))
fig.subplots_adjust(top=1 - 0.35 / figh, bottom=0.15 / figh,
left=0.2, right=0.99)
axs[0].set_title(f'{category} colormaps', fontsize=14)
for ax, name in zip(axs, cmap_list):
ax.imshow(gradient, aspect='auto', cmap=mpl.colormaps[name])
ax.text(-0.01, 0.5, name, va='center', ha='right', fontsize=10,
transform=ax.transAxes)
# Turn off *all* ticks & spines, not just the ones with colormaps.
for ax in axs:
ax.set_axis_off()
# Save colormap list for later.
cmaps[category] = cmap_list
Sequentiell#
Bei den sequentiellen Plots steigt der Helligkeitswert monoton durch die Colormaps an. Das ist gut. Einige der \(L^*\)-Werte in den Colormaps reichen von 0 bis 100 (binär und die anderen Graustufen), und andere beginnen bei etwa \(L^*=20\). Diejenigen mit einem kleineren Bereich von \(L^*\) haben entsprechend einen kleineren wahrnehmbaren Bereich. Beachten Sie auch, dass die \(L^*\)-Funktion zwischen den Colormaps variiert: einige sind ungefähr linear in \(L^*\) und andere sind stärker gekrümmt.
plot_color_gradients('Perceptually Uniform Sequential',
['viridis', 'plasma', 'inferno', 'magma', 'cividis'])

plot_color_gradients('Sequential',
['Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn'])

Sequentiell2#
Viele der \(L^*\)-Werte der Sequential2-Plots steigen monoton an, aber einige (autumn, cool, spring und winter) werden flach oder steigen und fallen sogar sowohl im als auch gegen den Uhrzeigersinn in \(L^*\)-Raum. Andere (afmhot, copper, gist_heat und hot) weisen Knicke in den \(L^*\)-Funktionen auf. Daten, die in einem Bereich der Colormap dargestellt werden, der sich an einem Plateau oder Knick befindet, führen zu einer Wahrnehmung von Banding der Daten in diesen Werten in der Colormap (siehe [mycarta-banding] für ein ausgezeichnetes Beispiel hierfür).
plot_color_gradients('Sequential (2)',
['binary', 'gist_yarg', 'gist_gray', 'gray', 'bone',
'pink', 'spring', 'summer', 'autumn', 'winter', 'cool',
'Wistia', 'hot', 'afmhot', 'gist_heat', 'copper'])

Divergierend#
Bei den Divergierenden Maps wollen wir monoton ansteigende \(L^*\)-Werte bis zu einem Maximum, das nahe bei \(L^*=100\) liegen sollte, gefolgt von monoton fallenden \(L^*\)-Werten haben. Wir suchen nach ungefähr gleichen minimalen \(L^*\)-Werten an gegenüberliegenden Enden der Colormap. Nach diesen Kriterien sind BrBG und RdBu gute Optionen. coolwarm ist eine gute Option, aber sie deckt keinen großen Bereich von \(L^*\)-Werten ab (siehe Graustufen-Abschnitt unten).
Berlin, Managua und Vanimo sind Dark-Mode-Divergenz-Colormaps mit minimaler Helligkeit in der Mitte und maximaler Helligkeit an den Extremen. Diese stammen aus F. Crameris [scientific-colour-maps] Version 8.0.1.
plot_color_gradients('Diverging',
['PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu', 'RdYlBu',
'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic',
'berlin', 'managua', 'vanimo'])

Zyklisch#
Für zyklische Maps wollen wir mit derselben Farbe beginnen und enden und uns in der Mitte symmetrisch treffen. Die \(L^*\) sollte monoton vom Start zur Mitte und umgekehrt von der Mitte zum Ende ansteigen. Sie sollte auf der steigenden und fallenden Seite symmetrisch sein und sich nur im Farbton unterscheiden. An den Enden und in der Mitte kehrt sich die \(L^*\)-Richtung um, was im \(L^*\)-Raum geglättet werden sollte, um Artefakte zu reduzieren. Weitere Informationen zum Design zyklischer Maps finden Sie unter [kovesi-colormaps].
Die häufig verwendete HSV-Colormap ist in dieser Colormap-Sammlung enthalten, obwohl sie nicht zu einem Mittelpunkt symmetrisch ist. Darüber hinaus variieren die \(L^*\)-Werte stark über die Colormap hinweg, was sie zu einer schlechten Wahl für die Darstellung von Daten für Betrachter macht, die sie wahrnehmungsbasiert sehen sollen. Siehe eine Erweiterung dieser Idee unter [mycarta-jet].
plot_color_gradients('Cyclic', ['twilight', 'twilight_shifted', 'hsv'])

Qualitativ#
Qualitative Colormaps sind nicht für die Wahrnehmung gedacht, aber ein Blick auf den Helligkeitsparameter kann uns das bestätigen. Die \(L^*\)-Werte bewegen sich während der gesamten Colormap wild durcheinander und steigen eindeutig nicht monoton an. Dies wären keine guten Optionen für die Verwendung als wahrnehmungsbasierte Colormaps.
plot_color_gradients('Qualitative',
['Pastel1', 'Pastel2', 'Paired', 'Accent', 'Dark2',
'Set1', 'Set2', 'Set3', 'tab10', 'tab20', 'tab20b',
'tab20c'])

Sonstiges#
Einige der verschiedenen Colormaps haben spezielle Verwendungszwecke, für die sie erstellt wurden. Zum Beispiel scheinen gist_earth, ocean und terrain für die Darstellung von Topografie (grün/braun) und Wassertiefen (blau) zusammen erstellt worden zu sein. Wir würden dann eine Divergenz in diesen Colormaps erwarten, aber mehrere Knicke sind möglicherweise nicht ideal, wie in gist_earth und terrain. CMRmap wurde entwickelt, um gut in Graustufen zu konvertieren, obwohl es einige kleine Knicke in \(L^*\) aufweist. cubehelix wurde entwickelt, um sich sowohl in Helligkeit als auch in Farbton gleichmäßig zu ändern, scheint aber eine kleine Wölbung im grünen Farbtonbereich zu haben. turbo wurde zur Darstellung von Tiefen- und Disparitätsdaten entwickelt.
Die häufig verwendete Jet-Colormap ist in dieser Sammlung von Colormaps enthalten. Wir sehen, dass die \(L^*\)-Werte während der gesamten Colormap stark variieren, was sie zu einer schlechten Wahl für die Darstellung von Daten macht, die Betrachter wahrnehmungsbasiert sehen sollen. Siehe eine Erweiterung dieser Idee unter [mycarta-jet] und [turbo].
plot_color_gradients('Miscellaneous',
['flag', 'prism', 'ocean', 'gist_earth', 'terrain',
'gist_stern', 'gnuplot', 'gnuplot2', 'CMRmap',
'cubehelix', 'brg', 'gist_rainbow', 'rainbow', 'jet',
'turbo', 'nipy_spectral', 'gist_ncar'])
plt.show()

Helligkeit von Matplotlib Colormaps#
Hier untersuchen wir die Helligkeitswerte der Matplotlib-Colormaps. Beachten Sie, dass einige Dokumentationen zu den Colormaps verfügbar sind ([list-colormaps]).
mpl.rcParams.update({'font.size': 12})
# Number of colormap per subplot for particular cmap categories
_DSUBS = {'Perceptually Uniform Sequential': 5, 'Sequential': 6,
'Sequential (2)': 6, 'Diverging': 6, 'Cyclic': 3,
'Qualitative': 4, 'Miscellaneous': 6}
# Spacing between the colormaps of a subplot
_DC = {'Perceptually Uniform Sequential': 1.4, 'Sequential': 0.7,
'Sequential (2)': 1.4, 'Diverging': 1.4, 'Cyclic': 1.4,
'Qualitative': 1.4, 'Miscellaneous': 1.4}
# Indices to step through colormap
x = np.linspace(0.0, 1.0, 100)
# Do plot
for cmap_category, cmap_list in cmaps.items():
# Do subplots so that colormaps have enough space.
# Default is 6 colormaps per subplot.
dsub = _DSUBS.get(cmap_category, 6)
nsubplots = int(np.ceil(len(cmap_list) / dsub))
# squeeze=False to handle similarly the case of a single subplot
fig, axs = plt.subplots(nrows=nsubplots, squeeze=False,
figsize=(7, 2.6*nsubplots))
for i, ax in enumerate(axs.flat):
locs = [] # locations for text labels
for j, cmap in enumerate(cmap_list[i*dsub:(i+1)*dsub]):
# Get RGB values for colormap and convert the colormap in
# CAM02-UCS colorspace. lab[0, :, 0] is the lightness.
rgb = mpl.colormaps[cmap](x)[np.newaxis, :, :3]
lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb)
# Plot colormap L values. Do separately for each category
# so each plot can be pretty. To make scatter markers change
# color along plot:
# https://stackoverflow.com/q/8202605/
if cmap_category == 'Sequential':
# These colormaps all start at high lightness, but we want them
# reversed to look nice in the plot, so reverse the order.
y_ = lab[0, ::-1, 0]
c_ = x[::-1]
else:
y_ = lab[0, :, 0]
c_ = x
dc = _DC.get(cmap_category, 1.4) # cmaps horizontal spacing
ax.scatter(x + j*dc, y_, c=c_, cmap=cmap, s=300, linewidths=0.0)
# Store locations for colormap labels
if cmap_category in ('Perceptually Uniform Sequential',
'Sequential'):
locs.append(x[-1] + j*dc)
elif cmap_category in ('Diverging', 'Qualitative', 'Cyclic',
'Miscellaneous', 'Sequential (2)'):
locs.append(x[int(x.size/2.)] + j*dc)
# Set up the axis limits:
# * the 1st subplot is used as a reference for the x-axis limits
# * lightness values goes from 0 to 100 (y-axis limits)
ax.set_xlim(axs[0, 0].get_xlim())
ax.set_ylim(0.0, 100.0)
# Set up labels for colormaps
ax.xaxis.set_ticks_position('top')
ticker = mpl.ticker.FixedLocator(locs)
ax.xaxis.set_major_locator(ticker)
formatter = mpl.ticker.FixedFormatter(cmap_list[i*dsub:(i+1)*dsub])
ax.xaxis.set_major_formatter(formatter)
ax.xaxis.set_tick_params(rotation=50)
ax.set_ylabel('Lightness $L^*$', fontsize=12)
ax.set_xlabel(cmap_category + ' colormaps', fontsize=14)
fig.tight_layout(h_pad=0.0, pad=1.5)
plt.show()
Konvertierung in Graustufen#
Es ist wichtig, die Konvertierung in Graustufen für Farbdarstellungen zu beachten, da diese möglicherweise auf Schwarzweißdruckern gedruckt werden. Wenn dies nicht sorgfältig bedacht wird, können Ihre Leser unverständliche Plots erhalten, da die Graustufen durch die Colormap unvorhersehbar verändert werden.
Die Konvertierung in Graustufen erfolgt auf viele verschiedene Arten [bw]. Einige der besseren verwenden eine lineare Kombination der RGB-Werte eines Pixels, aber gewichtet nach der Intensität der Farbwahrnehmung. Eine nichtlineare Methode der Konvertierung in Graustufen ist die Verwendung der \(L^*\)-Werte der Pixel. Im Allgemeinen gelten für diese Frage ähnliche Prinzipien wie für die wahrnehmungsbasierte Darstellung von Informationen; das heißt, wenn eine Colormap gewählt wird, die in \(L^*\)-Werten monoton ansteigt, wird sie in einer vernünftigen Weise in Graustufen gedruckt.
In diesem Sinne sehen wir, dass die sequentiellen Colormaps vernünftige Darstellungen in Graustufen aufweisen. Einige der Sequential2-Colormaps haben ausreichend gute Graustufendarstellungen, obwohl einige (autumn, spring, summer, winter) nur sehr geringe Graustufenänderungen aufweisen. Wenn eine Colormap wie diese in einem Plot verwendet und der Plot dann in Graustufen gedruckt würde, würden viele Informationen denselben Grauwerten zugeordnet werden. Die divergierenden Colormaps variieren meist von dunklerem Grau an den äußeren Rändern zu Weiß in der Mitte. Einige (PuOr und seismic) haben auf einer Seite merklich dunkleres Grau als auf der anderen und sind daher nicht sehr symmetrisch. coolwarm hat einen geringen Graustufenbereich und würde zu einer gleichmäßigeren Darstellung gedruckt, wobei viel Detail verloren geht. Beachten Sie, dass überlagerte, beschriftete Konturen helfen könnten, zwischen einer Seite der Colormap und der anderen zu unterscheiden, da Farbe nicht mehr verwendet werden kann, wenn ein Plot in Graustufen gedruckt wird. Viele der qualitativen und diversen Colormaps, wie Accent, hsv, jet und turbo, wechseln während der gesamten Colormap von dunkler zu heller und wieder zu dunklerem Grau. Dies würde es für einen Betrachter unmöglich machen, die Informationen in einem Plot zu interpretieren, sobald er in Graustufen gedruckt wurde.
mpl.rcParams.update({'font.size': 14})
# Indices to step through colormap.
x = np.linspace(0.0, 1.0, 100)
gradient = np.linspace(0, 1, 256)
gradient = np.vstack((gradient, gradient))
def plot_color_gradients(cmap_category, cmap_list):
fig, axs = plt.subplots(nrows=len(cmap_list), ncols=2)
fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99,
wspace=0.05)
fig.suptitle(cmap_category + ' colormaps', fontsize=14, y=1.0, x=0.6)
for ax, name in zip(axs, cmap_list):
# Get RGB values for colormap.
rgb = mpl.colormaps[name](x)[np.newaxis, :, :3]
# Get colormap in CAM02-UCS colorspace. We want the lightness.
lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb)
L = lab[0, :, 0]
L = np.float32(np.vstack((L, L, L)))
ax[0].imshow(gradient, aspect='auto', cmap=mpl.colormaps[name])
ax[1].imshow(L, aspect='auto', cmap='binary_r', vmin=0., vmax=100.)
pos = list(ax[0].get_position().bounds)
x_text = pos[0] - 0.01
y_text = pos[1] + pos[3]/2.
fig.text(x_text, y_text, name, va='center', ha='right', fontsize=10)
# Turn off *all* ticks & spines, not just the ones with colormaps.
for ax in axs.flat:
ax.set_axis_off()
plt.show()
for cmap_category, cmap_list in cmaps.items():
plot_color_gradients(cmap_category, cmap_list)
Farbsicht-Defizite#
Es gibt viele Informationen über Farbenblindheit (z.B. [colorblindness]). Darüber hinaus gibt es Werkzeuge, um Bilder so zu konvertieren, wie sie für verschiedene Arten von Farbsicht-Defiziten aussehen.
Die häufigste Form von Farbsicht-Defiziten betrifft die Unterscheidung zwischen Rot und Grün. Daher werden durch die Vermeidung von Colormaps mit sowohl Rot als auch Grün viele Probleme im Allgemeinen vermieden.
Referenzen#
Gesamtlaufzeit des Skripts: (0 Minuten 13,539 Sekunden)













