Matplotlib에서 컬러맵 선택 #

Matplotlib에는 matplotlib.colormaps. Matplotlib 설명서의 Third-party colormaps 섹션 에서 볼 수 있는 많은 추가 색상표가 있는 외부 라이브러리도 있습니다 . 여기서는 여러 옵션 중에서 선택하는 방법에 대해 간략하게 설명합니다. 고유한 컬러맵 생성에 대한 도움말은 Matplotlib에서 컬러맵 생성 을 참조하십시오 .

개요 #

좋은 컬러맵을 선택하는 이유는 데이터 세트에 대한 3D 색상 공간에서 좋은 표현을 찾는 것입니다. 주어진 데이터 세트에 대한 최상의 컬러맵은 다음을 비롯한 많은 요소에 따라 달라집니다.

  • 양식 또는 메트릭 데이터를 나타내는지 여부( [Ware] )

  • 데이터 세트에 대한 지식( 예: 다른 값에서 벗어나는 중요한 값이 있습니까?)

  • 플로팅 중인 매개변수에 대한 직관적인 색 구성표가 있는 경우

  • 현장에 표준이 있다면 청중이 기대할 수 있습니다.

많은 응용 프로그램에서 지각적으로 균일한 컬러맵이 최선의 선택입니다. 즉, 데이터의 동일한 단계가 색 공간에서 동일한 단계로 인식되는 컬러맵입니다. 연구자들은 인간의 두뇌가 예를 들어 색조의 변화보다 데이터의 변화로 밝기 매개변수의 변화를 훨씬 더 잘 인식한다는 사실을 발견했습니다. 따라서 컬러맵을 통해 밝기가 단조롭게 증가하는 컬러맵은 뷰어에서 더 잘 해석됩니다. 지각적으로 균일한 컬러맵의 훌륭한 예는 타사 컬러맵 섹션에서도 찾을 수 있습니다.

색상은 다양한 방법으로 3D 공간에서 표현될 수 있습니다. 색상을 표현하는 한 가지 방법은 CIELAB을 사용하는 것입니다. CIELAB에서 색공간은 밝기로 표현되며, \(L^*\); 적녹,\(a^*\); 그리고 노랑-파랑,\(b^*\). 밝기 매개변수\(L^*\)그런 다음 뷰어가 matplotlib 컬러맵을 인식하는 방법에 대해 자세히 알아보는 데 사용할 수 있습니다.

컬러맵에 대한 인간의 인식에 대해 학습하기 위한 훌륭한 시작 리소스는 [IBM] 에서 찾을 수 있습니다.

컬러맵 클래스 #

컬러맵은 종종 기능에 따라 여러 범주로 나뉩니다( 예: [ Moreland] 참조).

  1. 순차: 종종 단일 색조를 사용하여 밝기와 채도가 점진적으로 변경됩니다. 순서가 있는 정보를 나타내는 데 사용해야 합니다.

  2. 발산: 채도가 낮은 색상에서 중간에서 만나는 두 가지 다른 색상의 밝기 및 가능한 채도의 변화; 플롯되는 정보에 지형과 같은 중요한 중간 값이 있거나 데이터가 0 근처에서 벗어날 때 사용해야 합니다.

  3. 순환: 불포화 색상에서 중간과 시작/끝에서 만나는 서로 다른 두 색상의 밝기 변화; 위상 각도, 풍향 또는 하루 중 시간과 같이 끝점에서 둘러싸는 값에 사용해야 합니다.

  4. 정성적: 종종 잡다한 색상입니다. 순서나 관계가 없는 정보를 나타내는 데 사용해야 합니다.

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

먼저 각 컬러맵의 범위를 보여줍니다. 일부는 다른 것보다 더 "빠르게" 변하는 것처럼 보입니다.

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

순차적 #

Sequential 플롯의 경우 밝기 값은 컬러맵을 통해 단조롭게 증가합니다. 좋습니다. 일부\(L^*\)컬러맵의 값 범위는 0에서 100(이진 및 다른 그레이스케일)이고 다른 값은 대략 시작합니다. \(L^*=20\). 범위가 작은 분들은\(L^*\)따라서 지각 범위가 더 작아집니다. 또한\(L^*\)기능은 컬러맵에 따라 다릅니다. 일부는 대략 선형입니다.\(L^*\)다른 것들은 더 구부러져 있습니다.

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'])
순차적 컬러맵

순차 2 #

많은\(L^*\)Sequential2 플롯의 값은 단조롭게 증가하지만 일부(가을, 선선한, 봄, 겨울) 고원 또는\(L^*\)우주. 기타(afmhot, copper, gist_heat 및 hot)에는 꼬임이 있습니다.\(L^*\)기능. 안정기 또는 꼬임에 있는 컬러맵의 영역에서 표현되는 데이터는 컬러맵의 해당 값에서 데이터의 밴딩 인식으로 이어집니다( 이에 대한 훌륭한 예는 [mycarta-banding] 참조).

plot_color_gradients('Sequential (2)',
                     ['binary', 'gist_yarg', 'gist_gray', 'gray', 'bone',
                      'pink', 'spring', 'summer', 'autumn', 'winter', 'cool',
                      'Wistia', 'hot', 'afmhot', 'gist_heat', 'copper'])
순차(2) 컬러맵

발산 #

Diverging 맵의 경우 단조롭게 증가하고 싶습니다.\(L^*\) 값에 가까워야 하는 최대값\(L^*=100\), 단조롭게 감소\(L^*\)가치. 우리는 대략적으로 동등한 최소값을 찾고 있습니다.\(L^*\)컬러맵의 반대쪽 끝에 있는 값. 이러한 방법으로 BrBG 및 RdBu는 좋은 옵션입니다. coolwarm은 좋은 옵션이지만 광범위한 범위에 걸쳐 있지는 않습니다.\(L^*\)값(아래 그레이스케일 섹션 참조).

plot_color_gradients('Diverging',
                     ['PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu', 'RdYlBu',
                      'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic'])
다양한 컬러맵

순환 #

순환 맵의 경우 동일한 색상으로 시작하고 끝나며 중간에서 대칭 중심점을 만나고 싶습니다.\(L^*\)시작에서 중간으로, 중간에서 끝으로 역으로 단조롭게 변경되어야 합니다. 증가 및 감소 측면에서 대칭이어야 하며 색조만 다릅니다. 끝과 중간에,\(L^*\)부드럽게 해야 하는 방향을 바꿀 것입니다. \(L^*\)아티팩트를 줄이기 위한 공간. 순환 맵 설계에 대한 자세한 내용 은 [kovesi-colormaps] 를 참조하십시오.

자주 사용되는 HSV 컬러맵이 이 컬러맵 세트에 포함되어 있지만 중심점에 대해 대칭은 아닙니다. 또한,\(L^*\)값은 컬러맵 전체에서 매우 다양하므로 보는 사람이 지각할 수 있는 데이터를 나타내는 데 적합하지 않습니다. [mycarta-jet] 에서 이 아이디어에 대한 확장을 참조하십시오 .

plot_color_gradients('Cyclic', ['twilight', 'twilight_shifted', 'hsv'])
순환 컬러맵

질적 #

정성적 컬러맵은 지각적 맵을 목표로 하지 않지만 밝기 매개변수를 보면 이를 확인할 수 있습니다. 그만큼\(L^*\)값은 컬러맵 전체에서 이동하며 분명히 단조롭게 증가하지 않습니다. 이는 지각 컬러맵으로 사용하기에 좋은 옵션이 아닙니다.

plot_color_gradients('Qualitative',
                     ['Pastel1', 'Pastel2', 'Paired', 'Accent', 'Dark2',
                      'Set1', 'Set2', 'Set3', 'tab10', 'tab20', 'tab20b',
                      'tab20c'])
질적 컬러맵

기타 #

기타 컬러맵 중 일부는 생성된 특정 용도가 있습니다. 예를 들어 gist_earth, ocean 및 Terrain은 모두 지형(녹색/갈색)과 수심(파란색)을 함께 플로팅하기 위해 생성된 것으로 보입니다. 그러면 이러한 컬러맵에서 차이가 있을 것으로 예상되지만 gist_earth 및 지형과 같이 여러 꼬임이 이상적이지 않을 수 있습니다. CMRmap은 약간의 꼬임이 있는 것처럼 보이지만 그레이스케일로 잘 변환되도록 만들어졌습니다. \(L^*\). 큐브헬릭스는 명도와 색조가 모두 부드럽게 변하도록 만들어졌지만 녹색 색조 영역에 작은 혹이 있는 것처럼 보입니다. 터보는 깊이 및 시차 데이터를 표시하기 위해 만들어졌습니다.

자주 사용되는 제트 컬러맵이 이 컬러맵 세트에 포함되어 있습니다. 우리는\(L^*\)값은 컬러맵 전체에서 매우 다양하므로 보는 사람이 지각할 수 있는 데이터를 나타내는 데 적합하지 않습니다. [mycarta-jet][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()
기타 색상표

Matplotlib 컬러맵의 밝기 #

여기서 우리는 matplotlib 컬러맵의 밝기 값을 검사합니다. 컬러맵에 대한 일부 문서를 사용할 수 있습니다( [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()
  • 컬러맵
  • 컬러맵
  • 컬러맵
  • 컬러맵
  • 컬러맵
  • 컬러맵
  • 컬러맵

그레이스케일 변환 #

컬러 플롯은 흑백 프린터로 인쇄될 수 있으므로 그레이스케일로 변환하는 데 주의를 기울이는 것이 중요합니다. 신중하게 고려하지 않으면 컬러맵을 통해 회색조가 예측할 수 없게 변경되기 때문에 판독기가 해독할 수 없는 플롯으로 끝날 수 있습니다.

그레이스케일로의 변환은 다양한 방식으로 이루어집니다 [bw] . 더 나은 것 중 일부는 픽셀의 rgb 값의 선형 조합을 사용하지만 색상 강도를 인식하는 방법에 따라 가중치가 부여됩니다. 그레이스케일로 변환하는 비선형 방법은 다음을 사용하는 것입니다.\(L^*\)픽셀의 값. 일반적으로, 지각적으로 정보를 제시할 때와 마찬가지로 이 질문에도 유사한 원칙이 적용됩니다. 즉, 단조롭게 증가하는 컬러맵을 선택한 경우\(L^*\)값을 사용하면 합리적인 방식으로 그레이스케일로 인쇄됩니다.

이를 염두에 두고 Sequential 컬러맵이 회색조로 적절하게 표현된다는 것을 알 수 있습니다. Sequential2 컬러맵 중 일부는 적절한 그레이스케일 표현을 가지고 있지만 일부(가을, 봄, 여름, 겨울)는 그레이스케일 변화가 거의 없습니다. 이와 같은 컬러맵이 플롯에 사용된 다음 플롯이 회색조로 인쇄된 경우 많은 정보가 동일한 회색 값에 매핑될 수 있습니다. 다중 컬러맵은 대부분 외부 가장자리의 어두운 회색에서 중간의 흰색까지 다양합니다. 일부(PuOr 및 지진)는 한쪽이 다른 쪽보다 눈에 띄게 더 어두운 회색을 나타내므로 그다지 대칭적이지 않습니다. coolwarm은 그레이 스케일의 범위가 작고 더 균일한 플롯으로 인쇄하여 많은 세부 사항을 잃게 됩니다. 중첩되고 레이블이 지정된 윤곽선은 컬러맵의 한 쪽과 다른 쪽을 구별하는 데 도움이 될 수 있습니다. 다른 하나는 플롯이 그레이스케일로 인쇄되면 색상을 사용할 수 없기 때문입니다. Accent, hsv, jet 및 turbo와 같은 많은 정성 및 기타 컬러맵은 컬러맵 전체에서 어두운 색에서 밝은 색으로, 다시 어두운 회색으로 바뀝니다. 이렇게 하면 플롯이 그레이스케일로 인쇄되면 보는 사람이 플롯의 정보를 해석하는 것이 불가능해집니다.

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)
  • 지각적으로 균일한 순차 컬러맵
  • 순차적 컬러맵
  • 순차(2) 컬러맵
  • 다양한 컬러맵
  • 순환 컬러맵
  • 질적 컬러맵
  • 기타 색상표

색각 이상 #

색맹( 예: [ colorblindness] ) 에 대해 사용할 수 있는 정보가 많이 있습니다 . 또한 이미지를 다양한 유형의 색각 장애를 찾는 방식으로 변환하는 데 사용할 수 있는 도구가 있습니다.

가장 흔한 형태의 색각 이상은 빨간색과 녹색을 구분하는 것입니다. 따라서 빨간색과 녹색이 모두 포함된 컬러맵을 피하면 일반적으로 많은 문제를 피할 수 있습니다.

참조 #

스크립트의 총 실행 시간: (0분 14.251초)

Sphinx-Gallery에서 생성한 갤러리