Matplotlib配色之Colormap詳解

概述

上一篇詳細介紹瞭 matplotlib 直接使用”格式化的顏色定義”給圖表元素配色。如,直接指定 axes.plot 繪制的 Line2D 的顏色 fmt = 'r'

有時我們希望圖表元素的顏色與數據集中某個變量的值相關,顏色隨著該變量值的變化而變化,以反映數據變化趨勢、數據的聚集、分析者對數據的理解等信息,這時,我們就要用到 matplotlib 的顏色映射(colormap)功能,即將數據映射到顏色。

要實現數據到顏色的映射需要做兩件事:

  • 變量值的變化范圍很大,matplotlib用 [0, 1] 區間的浮點數表示顏色RGB值,首先需要將不同的變量值映射到[0, 1]區間;
  • 將映射[0, 1]區間的變量值映射到顏色。

matplotlib.colors 模塊是實現 colormap 配色功能的核心模塊。

  • 該模塊的Normalize()類及其子類完成第1個任務;
  • 該模塊的colormap類及其子類完成第2個任務。

將上述兩個類的實例,即:

  • 定義變量數據映射到[0, 1]區間的規則;
  • [0, 1]映射到顏色的規則。

作為參數傳遞給繪圖函數,即可實現顏色反映變量數據屬性的目的。參見下面的入門示例。

入門示例

我們先看一個示例,簡單、直觀地瞭解 matplotlib.colors模塊的工作原理。

使用有名的 Iris Data Set(鳶尾屬植物數據集)中的數據來演示圖表的繪制和配置,這樣更接近實際的應用。可以到QQ群:457079928中下載這個數據集iris.csv。

Iris 數據集首次出現在著名的英國統計學傢和生物學傢Ronald Fisher 1936年的論文《The use of multiple measurements in taxonomic problems》中,被用來介紹線性判別式分析。

在這個數據集中,包括瞭三類不同的鳶尾屬植物:Iris Setosa,Iris Versicolour,Iris Virginica。每類收集瞭50個樣本,因此這個數據集一共包含瞭150個樣本。

該數據集測量瞭 150 個樣本的 4 個特征,分別是:

  • sepal length(花萼長度)
  • sepal width(花萼寬度)
  • petal length(花瓣長度)
  • petal width(花瓣寬度)

以上四個特征的單位都是厘米(cm)。

%matplotlib inline

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt

iris_df = pd.read_csv('iris.csv',index_col='index_col')

#用花萼長度作為 x 值, 花萼寬度作為 y 值繪制散點圖
x = iris_df['PetalLength'].values
y = iris_df['SepalLength'].values

fig = plt.figure()
ax= plt.axes()

# 直接指定顏色
# 點的顏色都一樣,顏色不反映更多的信息
plt.scatter(x, y,c='g')

plt.show()

在這裡插入圖片描述

如果我們分析這個數據,圖中的點聚集成 3 個組,如下圖所示:

在這裡插入圖片描述

我們希望用點的顏色反映這種分組聚集的信息,可以這樣做:

  • 定義一個三個顏色的列表為 colormap;
  • 定義一個數據歸一化的實例,將希望關聯顏色的數據映射到[0, 1]區間;
  • 使用 cmap, norm 實現圖表元素的分組配色。
%matplotlib inline

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt

iris_df = pd.read_csv('../Topics/iris.csv',index_col='index_col')

x = iris_df['PetalLength'].values
y = iris_df['SepalLength'].values

fig = plt.figure()
ax= plt.axes()

#創建一個ListedColormap實例
#定義瞭[0, 1]區間的浮點數到顏色的映射規則
cmp = mpl.colors.ListedColormap(['r','g','b'])

# 創建一個BoundaryNorm實例
# BoundaryNorm是數據分組中數據歸一化比較好的方法
# 定義瞭變量值到 [0, 1]區間的映射規則,即數據歸一化
norm = mpl.colors.BoundaryNorm([0, 2, 6.4, 7], cmp.N)

#繪制散點圖,用x值著色,
#使用norm對變量值進行歸一化,
#使用自定義的ListedColormap顏色映射實例
#norm將變量x的值歸一化
#cmap將歸一化的數據映射到顏色
plt.scatter(x,y,c=x, cmap=cmp, norm=norm, alpha=0.7)

plt.show()

在這裡插入圖片描述

上圖就比較直觀地反映瞭數據的分組信息。

上面的示例使用瞭 colors 模塊中的主要功能,下面就詳細討論該模塊的架構。

maplotlib.colors 模塊

matplotlib.colors模塊的架構如下圖所示:

在這裡插入圖片描述

matplotlib.colors模塊定義瞭11個類,定義瞭10個模塊命名空間的方法。

matplotlib.colors模塊的主要功能就是將數字或顏色參數轉換為RGBRGBA

RGBRGBA分別是0-1范圍內3個或4個浮點數的序列。參見上一篇 matplotlib 顏色定義格式規范中的相關內容。

此模塊包括:

用於將數字歸一化的類和方法,即將列表中的數據映射到 [0,1]區間的浮點數;

用於將歸范化後的數字映射到一維數組中的顏色,稱之為 colormap。

理解 matplotlib.colors 模塊的工作

  • 構建一個[0,1][0, 255]區間,該區間上有256個點;請想像把這256個點從左到右排列成一個長條;
  • 通過Normalize類(或者它的子類,映射方法不同)將數據映射到這個區間,比如上例中’PetalLength’數據區間是[1.0, 6.9], 就將區間[1.0, 6.9]映射到[0, 1]; 上例中定義瞭一個BoundaryNorm實例;
  • 構建一個colormap(通常是它的子類)實例,該實例是一個顏色名稱列表,或者浮點數數組表示的RGB值;
  • 這個顏色列表依次排列在[0, 1]這個區間的256個點上,但每個顏色(colormap中列出的顏色)占用的位置和區間則由Normalize指定;上例中定義一個cmp = mpl.colors.ListedColormap(['r','g','b']),列出瞭3種顏色;
  • 如果沒有定義colormap,則默認使用rc image.cmap中的設置;
  • 如果不指定Normalize,則默認使用colors.Normalize

 matplotlib.Colormap類及其子類

matplotlib.colors模塊的Colormap類是一個基類,提供瞭將[0, 1]的數據映射到顏色的一些屬性和方法供其子類使用,很少直接使用該基類,主要使用它的兩個子類:

  • ListedColrmap()
  • LinearSegmentedColormap()

這兩個子類就是兩種不同的映射方法。

colors.ListedColormap()子類

ListedColormap()類從顏色列表生成一個colormap

class matplotlib.colors.ListedColormap(colors, name='from_list', N=None)

**colors**參數有兩種形式:

  • matplotlib 接受的規范的顏色列表,如['r', 'g', 'b'], 或['C0', 'C3', 'C7'],等,詳見基礎篇;
  • [0, 1]區間的浮點數表示的RGB (N3)或 RGBA (N4)的數組,如:array((0.9, 0.1, 0.1),(0.1, 0.9, 0.1),(0.1, 0.1, 0.9))

colors = ['r', 'g', 'b']為例:

就是將[0, 1]區間劃分為三段,第一段映射為’r’色,第二段映射為’g’色,第三段映射為’b’色。

請看下面的示例:

#本示例演示對散點條分段著不同顏色

%matplotlib inline

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.colors

x= np.linspace(1, 12, 24, endpoint=True)
y=x/x

fig = plt.figure()
ax= plt.axes()

# 將`[0, 1]`區間簡單地分成四段,依次映射為列表`['r','g','b','y']`中列出的顏色
cmp = mpl.colors.ListedColormap(['r','g','b','y'])

#繪制散點圖,用x值著色
#沒有指定Norm,所以使用默認的`colors.Normalize`
#將x的值區間為 [1, 24]`映射(歸一化)到`[0, 1]`區間
plt.scatter(x, y,s=120, marker='s', c=x, cmap=cmp)

plt.show()

在這裡插入圖片描述

參數 Name

可選參數。

給自定義的Colormap命名,將這個Colormap註冊到matplotlib,後面即可以通過名稱來反復調用該colormap。

參數 N

可選參數。

從列表中的顏色輸入到映射的顏色數量。默認為None,即列表中的每個顏色都作為一項輸入到映射中。簡單地說,就是選用列表中的顏色數量。如果

  • N < len(colors),列表被截斷,即選用列表前N個顏色,後面的丟棄。
  • N > len(colors),通過重復列表以擴展列表。
#本示例演示瞭參數 N 的用法

%matplotlib inline

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.colors

x= np.linspace(1, 12, 24, endpoint=True)
y=x/x

fig = plt.figure()
ax= plt.axes()
ax.set_ylim(0.6, 1.5)

# 將`[0, 1]`區間簡單地分成 N 段
# 由於N>len(colors),所以重復列表以擴展顏色列表
cmp = mpl.colors.ListedColormap(['C2','C5','C0','C8'],N=6)

# N<len(colors),所以截斷顏色列表
cmp2 = mpl.colors.ListedColormap(['C2','C5','C0','C8'],N=2)

#繪制散點圖,用x值著色
#沒有指定Norm,所以使用默認的`colors.Normalize`
#將x的值區間為 [1, 24]`映射(歸一化)到`[0, 1]`區間
plt.scatter(x, x/x*1.1,s=120, marker='s', c=x, cmap=cmp)

plt.scatter(x, x/x*0.9,s=120, marker='s', c=x, cmap=cmp2)

plt.show()

在這裡插入圖片描述

colors.LinearSegmentedColormap()子類

class matplotlib.colors.LinearSegmentedColormap(name, segmentdata, N=256, gamma=1.0)

基於線性分段的查找表,從線性映射段創建顏色映射 Colormap 對象。

線性分段查找表是使用對每個原色進行線性插值生成的。

segmentdata參數就是這個線性分段查找表。

segmentdata是一個帶’red’、‘green’、’blue’元素項的字典,即這個字典有三個keys:‘red’、‘green’、‘blue’。

每個健的值是一個列表,值列表的元素是形如: (x, y0, y1) 的元組,每個元組是列表的一行。

註意: ‘red’、‘green’、’blue’元素項不能少。

該字典中每個鍵的值列表的形式如下:

在這裡插入圖片描述

表中給定顏色的每一行都是形如 x, y0, y1 的元組,若幹個元組構成列表。

在每個鍵的值序列中,x 必須從 0 到 1 單調增加。對於介於 x[i]x[i+1] 之間的任何輸入值 z, 給定顏色的輸出值將在 y1[i] 和 *y0[i+1]*之間線性插值。

理解線性分段查找表segmentdata

colors.LinearSegmentedColormap()子類在[0,1]區間上每個點的顏色是由該點的’red’、‘green’、’blue’三原色的值混合確定;

segmentdata 參數以一個字典形式提供每一段三原色值;

每個原色在[0, 1]區間上可以分段,分幾段由鍵值對中值列表的行數決定,分段的點則由元組(x, y0, y1)中的x值決定,如:

'red':  [(0.0, 0.0, 0.0),
     (0.4, 1.0, 1.0),
     (1.0, 1.0, 1.0)]

表示:

[0, 1]區間分成兩段,以 0.4 的位置為斷點;
[0, 0.4]區間段內,’red’的值從 0.0 線性增加到 1.0;
[0.4, 1.0]區間段內,’red’的值保持 1.0 不變。

  • ‘green’, ‘blue’值依此類推;
  • 每個點的顏色則由三原色值混合而成。
#本示例演示 LinearSegmentedColormap 映射用法
#對數據分段,每一段的內部通過線性插值獲得顏色值
#請註意比較與ListedColormap的不同

%matplotlib inline

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt

x= np.linspace(1, 12, 24, endpoint=True)
y=x/x

fig = plt.figure()
ax= plt.axes()
ax.set_ylim(0.5,1.1)

# 在0.4位置設置斷點,分為兩段
# 從0.0到0.4之間的 red 值是從 1.0 到 0.0 線性插值生成的(即漸變的),即從紅色到黑色
# green, blue的值從開始點到結束點都是零
# 從 0.4 到 1.0,則始終是紅色

cdict1 = {'red':  [(0.0, 0.0, 1.0),
          (0.4, 0.0, 1.0),
          (1.0, 1.0, 1.0)],

     'green': [(0.0, 0.0, 0.0),
          (1.0, 0.0, 0.0)],

     'blue': [(0.0, 0.0, 0.0),
          (1.0, 0.0, 0.0)]}

#將斷點設置在0.8的位置
cdict2 = {'red':  [(0.0, 0.0, 1.0),
          (0.8, 0.0, 1.0),
          (1.0, 1.0, 1.0)],

     'green': [(0.0, 0.0, 0.0),
          (1.0, 0.0, 0.0)],

     'blue': [(0.0, 0.0, 0.0),
          (1.0, 0.0, 0.0)]}


cmp1 = mpl.colors.LinearSegmentedColormap('name',cdict1)

cmp2 = mpl.colors.LinearSegmentedColormap('name',cdict2)


#繪制散點圖,用x值著色
plt.scatter(x, x/x*0.9,s=120,marker='s',c=x,cmap=cmp1,edgecolor='black')

plt.scatter(x, x/x*0.7,s=120,marker='s',c=x,cmap=cmp2,edgecolor='black')

plt.show()

在這裡插入圖片描述

# 再看一個示例

%matplotlib inline

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt

x= np.linspace(1, 12, 24, endpoint=True)
y=x/x

fig = plt.figure()
ax= plt.axes()

cdict = {'red':  [(0.0, 0.0, 0.2),
          (0.5, 1.0, 1.0),
          (1.0, 1.0, 1.0)],

     'green': [(0.0, 0.0, 0.5),
          (0.75, 1.0, 1.0),
          (1.0, 1.0, 1.0)],

     'blue': [(0.0, 0.0, 0.3),
          (0.25,0.0, 0.0 ),
          (0.5, 0.0, 0.0),
          (1.0, 1.0, 1.0)]}

cmp = mpl.colors.LinearSegmentedColormap('lsc',segmentdata=cdict)

#繪制散點圖,用x值著色
plt.scatter(x, y,s=120,marker='s',c=x,cmap=cmp,edgecolor='black')

plt.show()

在這裡插入圖片描述

matplotlib.cm 模塊

matplotlib.colors模塊:

  • 用於構建一個[0, 1]的標量數據到顏色的映射,Colormap 實例;
  • 將實際數據歸一化到[0, 1]區間,Normalize及其子類的實例。

有時我們還需要對上述實例進行一些處理,如將自定義的Colormap註冊到matplotlib,後面通過其名稱調用它;查詢Colormap在某個數據歸一化方法下各點的RGBA值。

matplotlib設計瞭cm模塊,提供瞭:

  • 內置的顏色映射 colormap,將顏色名稱映射到標準的顏色定義;
  • colormap 處理工具;
  • 如註冊一個Colormap,通過名稱獲取一個Colormap;
  • ScalarMappable 混合類,這個混合類用以支持將標量數據映射到RGBA顏色。ScalarMappable 在從給定的colormap返回RGBA顏色之前使用數據歸一化化。

cm模塊設計瞭 1 個混合類,提供瞭17個函數方法。

其中有3個函數方法屬於模塊空間:

  • matplotlib.cm.get_cmap(name=None, lut=None)
  • matplotlib.cm.register_cmap(name=None, cmap=None, data=None, lut=None)
  • matplotlib.cm.revcmap(data)

有14個函數方法屬於ScalarMappable類空間:

  • add_checker(self, checker)
  • autoscale(self)
  • autoscale_None(self)
  • changed(self)
  • check_update(self, checker)
  • get_alpha(self)
  • get_array(self)
  • get_clim(self)
  • get_cmap(self)
  • set_array(self, A)
  • set_clim(self, vmin=None, vmax=None)
  • set_cmap(self, cmap)
  • set_norm(self, norm)
  • to_rgba(self, x, alpha=None, bytes=False, norm=True)

class ScalarMappable

class matplotlib.cm.ScalarMappable(norm=None, cmap=None)

ScalarMappable混合類,用於支持標量數據到RGBA的映射。在從給定的colormap中返回RGBA顏色之前,ScalarMappable利用瞭數據歸一化。

註: 使用瞭ScalarMappable實例的to_rgba()方法。

matplotlib.cm.ScalarMappable 類充分利用data->normalize->map-to-color處理鏈,以簡化操作的步驟。

ScaplarMapable類以matplotlib.colors模塊的 Normalize實例和Colormap實例為參數。

如果是norm = None, norm 默認為colors.Normalize對象。

Colormap 有三個來源:

  • 內置的;
  • 第三方的colormap庫;
  • 自定義的。

如果為None,默認為rcParams.image.cmap中的設置。

matplotlib.colorsmatplotlib.cm 模塊的關系如下圖所示:

在這裡插入圖片描述

%matplotlib inline
​
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
​
x= np.linspace(1, 12, 24, endpoint=True)
y=x/x
​
fig = plt.figure()
ax= plt.axes()
ax.set_ylim(0.8, 1.2)
​
#傳遞不同的cmap
#繪制散點圖,用x值著色
plt.scatter(x, y*1.05,s=120, marker='s',c=x, cmap='viridis')
plt.scatter(x, y*0.95,s=120, marker='s',c=x, cmap='magma')
​
plt.show()

在這裡插入圖片描述

#觀察相同的cmap,不同的Norm,返回的RGBA值
norm1 = mpl.colors.LogNorm()
norm2 = mpl.colors.TwoSlopeNorm(0.4)

sm1 = mpl.cm.ScalarMappable(norm1, 'viridis')
sm2 = mpl.cm.ScalarMappable(norm2, 'viridis')

在這裡插入圖片描述

在這裡插入圖片描述

#觀察相同的Norm, 不同的cmap,返回的RGBA值
norm = mpl.colors.LogNorm()

sm3 = mpl.cm.ScalarMappable(norm, 'viridis')
sm4 = mpl.cm.ScalarMappable(norm, 'magma')

在這裡插入圖片描述

在這裡插入圖片描述

再看一個實例

%matplotlib inline

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt

iris_df = pd.read_csv('iris.csv',index_col='index_col')
iris_df.head()

petal_l = iris_df['PetalLength'].values
sepal_l = iris_df['SepalLength'].values

x = petal_l
y = sepal_l

fig = plt.figure()
ax= plt.axes()

#調用cm.get_cmap()方法,
#獲取內置的名為'ocean'的olormap實例
cmp = plt.get_cmap('ocean')

#創建一個Normalize實例
norm = plt.Normalize(vmin=np.min(x),vmax=np.max(x))

#繪制散點圖,用x值著色,
#使用norm對進行歸一化,
#使用內置的'ocean'映射
plt.scatter(x, y,c=x,cmap=cmp,norm=norm)

plt.show()

在這裡插入圖片描述

到此這篇關於Matplotlib配色之Colormap詳解的文章就介紹到這瞭,更多相關Matplotlib Colormap內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: