Matplotlib配⾊之Colormap详解
概述
上⼀篇详细介绍了 matplotlib 直接使⽤"格式化的颜⾊定义"给图表元素配⾊。如,直接指定axes.plot绘制的 Line2D 的颜⾊fmt = 'r'。
有时我们希望图表元素的颜⾊与数据集中某个变量的值相关,颜⾊随着该变量值的变化⽽变化,以反映数据变化趋势、数据的聚集、分析者对数据的理解等信息,这时,我们就要⽤到 matplotlib 的颜⾊映射(colormap)功能,即将数据映射到颜⾊。
要实现数据到颜⾊的映射需要做两件事:
变量值的变化范围很⼤,matplotlib⽤[0, 1]区间的浮点数表⽰颜⾊RGB值,⾸先需要将不同的变量值映射到[0, 1]区间;
将映射[0, 1]区间的变量值映射到颜⾊。
该模块的Normalize()类及其⼦类完成第1个任务;
该模块的colormap类及其⼦类完成第2个任务。
将上述两个类的实例,即:
定义变量数据映射到[0, 1]区间的规则;
和[0, 1]映射到颜⾊的规则。
作为参数传递给绘图函数,即可实现颜⾊反映变量数据属性的⽬的。参见下⾯的⼊门⽰例。
⼊门⽰例
我们先看⼀个⽰例,简单、直观地了解lors模块的⼯作原理。
使⽤有名的 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 = lors.ListedColormap(['r','g','b'])
# 创建⼀个BoundaryNorm实例
# BoundaryNorm是数据分组中数据归⼀化⽐较好的⽅法
# 定义了变量值到 [0, 1]区间的映射规则,即数据归⼀化
norm = lors.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 模块中的主要功能,下⾯就详细讨论该模块的架构。lors 模块
RGB和RGBA分别是0-1范围内3个或4个浮点数的序列。参见上⼀篇 matplotlib 颜⾊定义格式规范中的相关内容。
此模块包括:
⽤于将数字归⼀化的类和⽅法,即将列表中的数据映射到[0,1]区间的浮点数;
⽤于将归范化后的数字映射到⼀维数组中的颜⾊,称之为 colormap。
理解 lors 模块的⼯作
构建⼀个[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 =
如果没有定义colormap,则默认使⽤ap中的设置;
如果不指定Normalize,则默认使⽤colors.Normalize。
matplotlib.Colormap类及其⼦类
LinearSegmentedColormap()
这两个⼦类就是两种不同的映射⽅法。
colors.ListedColormap()⼦类
ListedColormap()类从颜⾊列表⽣成⼀个colormap。
lors.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
lors
x= np.linspace(1, 12, 24, endpoint=True)
y=x/x
fig = plt.figure()
ax= plt.axes()
# 将`[0, 1]`区间简单地分成四段,依次映射为列表`['r','g','b','y']`中列出的颜⾊
cmp = lors.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。
linspace numpy参数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
lors
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 = lors.ListedColormap(['C2','C5','C0','C8'],N=6)
# N<len(colors),所以截断颜⾊列表
cmp2 = lors.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()⼦类
lors.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 = lors.LinearSegmentedColormap('name',cdict1)
cmp2 = lors.LinearSegmentedColormap('name',cdict2)
#绘制散点图,⽤x值着⾊

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。