Auswahl von Colormaps in Matplotlib #

Matplotlib verfügt über eine Reihe integrierter Farbkarten, auf die über matplotlib.colormaps. Es gibt auch externe Bibliotheken mit vielen zusätzlichen Farbkarten, die im Abschnitt Farbkarten von Drittanbietern der Matplotlib-Dokumentation eingesehen werden können . Hier besprechen wir kurz, wie Sie zwischen den vielen Optionen wählen können. Hilfe zum Erstellen eigener Colormaps finden Sie unter Erstellen von Colormaps in Matplotlib .

Übersicht #

Die Idee hinter der Auswahl einer guten Farbkarte ist, eine gute Darstellung im 3D-Farbraum für Ihren Datensatz zu finden. Die beste Farbkarte für einen bestimmten Datensatz hängt von vielen Dingen ab, darunter:

  • Ob Form- oder Metrikdaten dargestellt werden ( [Ware] )

  • Ihre Kenntnis des Datensatzes ( z . B. gibt es einen kritischen Wert, von dem die anderen Werte abweichen?)

  • Wenn es ein intuitives Farbschema für den zu plottenden Parameter gibt

  • Wenn es einen Standard auf diesem Gebiet gibt, kann das Publikum erwarten

Für viele Anwendungen ist eine wahrnehmbar einheitliche Farbkarte die beste Wahl; dh eine Farbkarte, in der gleiche Schritte in Daten als gleiche Schritte im Farbraum wahrgenommen werden. Forscher haben herausgefunden, dass das menschliche Gehirn Änderungen des Helligkeitsparameters viel besser als Änderungen der Daten wahrnimmt als beispielsweise Änderungen des Farbtons. Daher werden Farbabbildungen, die eine durch die Farbabbildung monoton zunehmende Helligkeit aufweisen, vom Betrachter besser interpretiert. Wunderbare Beispiele für wahrnehmbar einheitliche Farbkarten finden Sie auch im Abschnitt Farbkarten von Drittanbietern .

Farbe kann im 3D-Raum auf verschiedene Weise dargestellt werden. Eine Möglichkeit, Farbe darzustellen, ist die Verwendung von CIELAB. In CIELAB wird der Farbraum durch Helligkeit dargestellt, \(L^*\); rot grün,\(a^*\); und gelb-blau,\(b^*\). Der Helligkeitsparameter\(L^*\)kann dann verwendet werden, um mehr darüber zu erfahren, wie die Matplotlib-Farbkarten von den Betrachtern wahrgenommen werden.

Eine ausgezeichnete Ausgangsquelle, um etwas über die menschliche Wahrnehmung von Farbkarten zu lernen, ist von [IBM] .

Klassen von Colormaps #

Colormaps werden aufgrund ihrer Funktion oft in mehrere Kategorien eingeteilt (siehe z . B. [Moreland] ):

  1. Sequenziell: schrittweise Änderung der Helligkeit und häufig Sättigung der Farbe, häufig unter Verwendung eines einzelnen Farbtons; sollte verwendet werden, um Informationen darzustellen, die eine Ordnung haben.

  2. Divergenz: Helligkeitsänderung und ggf. Sättigung zweier unterschiedlicher Farben, die sich in der Mitte bei einer ungesättigten Farbe treffen; sollte verwendet werden, wenn die aufzuzeichnenden Informationen einen kritischen Mittelwert haben, wie z. B. die Topographie, oder wenn die Daten um Null herum abweichen.

  3. Zyklisch: Helligkeitsänderung zweier unterschiedlicher Farben, die sich in der Mitte treffen und an einer ungesättigten Farbe beginnen/enden; sollte für Werte verwendet werden, die an den Endpunkten umlaufen, wie z. B. Phasenwinkel, Windrichtung oder Tageszeit.

  4. Qualitativ: sind oft verschiedene Farben; sollte verwendet werden, um Informationen darzustellen, die keine Ordnung oder Beziehungen haben.

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from colorspacious import cspace_converter

Zuerst zeigen wir den Bereich jeder Farbkarte. Beachten Sie, dass sich einige "schneller" zu ändern 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

Fortlaufende #

Bei den sequentiellen Diagrammen steigt der Helligkeitswert monoton durch die Farbtabellen. Das ist gut. Manche der\(L^*\)Werte in den Colormaps reichen von 0 bis 100 (binär und die anderen Graustufen), und andere beginnen herum \(L^*=20\). Diejenigen, die eine kleinere Reichweite haben\(L^*\)wird dementsprechend einen kleineren Wahrnehmungsbereich haben. Beachten Sie auch, dass die\(L^*\)Die Funktion variiert zwischen den Farbkarten: Einige sind ungefähr linear in\(L^*\)und andere sind gekrümmter.

plot_color_gradients('Perceptually Uniform Sequential',
                     ['viridis', 'plasma', 'inferno', 'magma', 'cividis'])
Wahrnehmungsgleiche sequentielle Farbkarten
plot_color_gradients('Sequential',
                     ['Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
                      'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
                      'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn'])
Sequentielle Farbkarten

Sequentiell2 #

Viele der\(L^*\)Werte aus den Sequential2-Plots steigen monoton, aber einige (Herbst, Kühle, Frühling und Winter) haben ein Plateau oder gehen sogar sowohl nach oben als auch nach unten\(L^*\)Platz. Andere (afmhot, copper, gist_heat und hot) haben Knicke in der\(L^*\)Funktionen. Daten, die in einem Bereich der Farbkarte dargestellt werden, der sich auf einem Plateau oder Knick befindet, führen zu einer Wahrnehmung von Banding der Daten in diesen Werten in der Farbkarte (siehe [mycarta-banding] für ein hervorragendes Beispiel dafü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'])
Sequentielle (2) Farbkarten

Abweichend #

Für die divergierenden Karten wollen wir monoton ansteigend haben\(L^*\) Werte bis zu einem Maximum, das in der Nähe sein sollte\(L^*=100\), gefolgt von monoton abnehmendem\(L^*\)Werte. Wir suchen ein ungefähr gleiches Minimum\(L^*\)Werte an gegenüberliegenden Enden der Farbtabelle. Durch diese Maßnahmen sind BrBG und RdBu gute Optionen. coolwarm ist eine gute Option, deckt aber keine große Bandbreite ab\(L^*\)Werte (siehe Abschnitt Graustufen weiter unten).

plot_color_gradients('Diverging',
                     ['PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu', 'RdYlBu',
                      'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic'])
Abweichende Farbkarten

Zyklisch #

Bei zyklischen Karten möchten wir mit derselben Farbe beginnen und enden und einen symmetrischen Mittelpunkt in der Mitte treffen.\(L^*\)sollte sich monoton von Anfang bis Mitte und umgekehrt von Mitte bis Ende ändern. Es sollte auf der steigenden und fallenden Seite symmetrisch sein und sich nur im Farbton unterscheiden. An den Enden und in der Mitte,\(L^*\)wird die Richtung umkehren, die geglättet werden sollte \(L^*\)Raum, um Artefakte zu reduzieren. Siehe [kovesi-colormaps] für weitere Informationen zum Design zyklischer Karten.

Die häufig verwendete HSV-Farbkarte ist in diesem Satz von Farbkarten enthalten, obwohl sie nicht symmetrisch zu einem Mittelpunkt ist. Zusätzlich die\(L^*\)Die Werte variieren stark über die Farbkarte hinweg, was sie zu einer schlechten Wahl für die Darstellung von Daten macht, die Betrachter wahrnehmungsmäßig sehen können. Eine Erweiterung dieser Idee finden Sie unter [mycarta-jet] .

plot_color_gradients('Cyclic', ['twilight', 'twilight_shifted', 'hsv'])
Zyklische Farbkarten

Qualitativ #

Qualitative Farbkarten zielen nicht darauf ab, Wahrnehmungskarten zu sein, aber ein Blick auf den Helligkeitsparameter kann dies für uns bestätigen. Das\(L^*\)Werte bewegen sich überall in der Farbkarte und steigen eindeutig nicht monoton an. Dies wären keine guten Optionen für die Verwendung als perzeptive Farbkarten.

plot_color_gradients('Qualitative',
                     ['Pastel1', 'Pastel2', 'Paired', 'Accent', 'Dark2',
                      'Set1', 'Set2', 'Set3', 'tab10', 'tab20', 'tab20b',
                      'tab20c'])
Qualitative Farbkarten

Sonstiges #

Einige der verschiedenen Farbkarten haben bestimmte Verwendungszwecke, für die sie erstellt wurden. Zum Beispiel scheinen gist_earth, Ocean und Terrain alle dafür geschaffen zu sein, Topographie (grün/braun) und Wassertiefen (blau) zusammen darzustellen. Wir würden also eine Abweichung in diesen Farbkarten erwarten, aber mehrere Knicke sind möglicherweise nicht ideal, wie z. B. in gist_earth und Terrain. CMRmap wurde erstellt, um gut in Graustufen zu konvertieren, obwohl es einige kleine Knicke zu haben scheint \(L^*\). cubehelix wurde so erstellt, dass es sowohl in der Helligkeit als auch im Farbton sanft variiert, scheint aber einen kleinen Buckel im grünen Farbtonbereich zu haben. turbo wurde entwickelt, um Tiefen- und Disparitätsdaten anzuzeigen.

Die häufig verwendete Jet-Farbkarte ist in diesem Satz von Farbkarten enthalten. Wir können sehen, dass die\(L^*\)Die Werte variieren stark über die Farbkarte hinweg, was sie zu einer schlechten Wahl für die Darstellung von Daten macht, die Betrachter wahrnehmungsmäßig sehen können. Eine Erweiterung dieser Idee finden Sie 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()
Diverse Farbkarten

Helligkeit von Matplotlib-Farbkarten #

Hier untersuchen wir die Helligkeitswerte der Matplotlib-Colormaps. Beachten Sie, dass eine Dokumentation zu den Farbkarten verfügbar ist ( [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()
  • Farbkarten
  • Farbkarten
  • Farbkarten
  • Farbkarten
  • Farbkarten
  • Farbkarten
  • Farbkarten

Graustufenkonvertierung #

Es ist wichtig, bei Farbplots auf die Konvertierung in Graustufen zu achten, da diese möglicherweise auf Schwarzweißdruckern gedruckt werden. Wenn Sie nicht sorgfältig überlegen, erhalten Ihre Leser möglicherweise nicht entzifferbare Diagramme, da sich die Graustufen durch die Farbtabelle unvorhersehbar ändern.

Die Konvertierung in Graustufen erfolgt auf viele verschiedene Arten [bw] . Einige der besseren verwenden eine lineare Kombination der RGB-Werte eines Pixels, jedoch gewichtet nach unserer Wahrnehmung der Farbintensität. Eine nichtlineare Methode zur Umwandlung in Graustufen ist die Verwendung von\(L^*\)Werte der Pixel. Im Allgemeinen gelten für diese Frage ähnliche Prinzipien wie für die wahrnehmungsbezogene Darstellung von Informationen; das heißt, wenn eine Farbtabelle gewählt wird, die monoton ansteigt\(L^*\)Werte, wird es vernünftigerweise in Graustufen gedruckt.

Vor diesem Hintergrund sehen wir, dass die sequentiellen Farbkarten eine vernünftige Darstellung in Graustufen haben. Einige der Sequential2-Colormaps haben ausreichend anständige Graustufendarstellungen, obwohl einige (Herbst, Frühling, Sommer, Winter) nur sehr geringe Graustufenänderungen aufweisen. Wenn eine Farbkarte wie diese in einem Diagramm verwendet wurde und das Diagramm dann in Graustufen gedruckt wurde, werden viele Informationen möglicherweise denselben Grauwerten zugeordnet. Die divergierenden Farbkarten variieren meist von dunklerem Grau an den äußeren Rändern bis hin zu Weiß in der Mitte. Einige (PuOr und seismisch) haben auf einer Seite ein deutlich dunkleres Grau als auf der anderen und sind daher nicht sehr symmetrisch. coolwarm hat einen geringen Graustufenbereich und würde zu einem gleichmäßigeren Plot drucken, wodurch viele Details verloren gehen. Beachten Sie, dass überlagerte, beschriftete Konturen dabei helfen können, zwischen einer Seite der Farbkarte und einer Seite zu unterscheiden. die andere, da Farbe nicht verwendet werden kann, sobald ein Diagramm in Graustufen gedruckt wurde. Viele der qualitativen und sonstigen Farbkarten, wie Accent, hsv, jet und turbo, ändern sich in der gesamten Farbkarte von dunklerem zu hellerem und zurück zu dunklerem Grau. Dies würde es einem Betrachter unmöglich machen, die Informationen in einem Diagramm zu interpretieren, sobald es in Graustufen gedruckt ist.

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)
  • Wahrnehmungsgleiche sequentielle Farbkarten
  • Sequentielle Farbkarten
  • Sequentielle (2) Farbkarten
  • Abweichende Farbkarten
  • Zyklische Farbkarten
  • Qualitative Farbkarten
  • Diverse Farbkarten

Farbsehstörungen #

Es gibt viele Informationen über Farbenblindheit ( z . B. [Farbenblindheit] ). Darüber hinaus stehen Tools zur Verfügung, mit denen Bilder so konvertiert werden können, wie sie für verschiedene Arten von Farbsehschwächen aussehen.

Die häufigste Form der Farbsehschwäche ist die Unterscheidung zwischen Rot und Grün. Das Vermeiden von Colormaps mit Rot und Grün wird daher im Allgemeinen viele Probleme vermeiden.

Referenzen #

Gesamtlaufzeit des Skripts: ( 0 Minuten 14.251 Sekunden)

Galerie generiert von Sphinx-Gallery