Matplotlib是Python生态圈中应用最为广泛的2D绘图库,通过扩展工具包mplot3d,也可以绘制简单的3D模型。Matplotlib的使用非常简单,以绘制一条单周期的正弦曲线为例,只需要寥寥数行代码即可完成。

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2*np.pi, 200)
y = np.sin(x)
plt.plot(x, y, color='green')
plt.show()

上面的代码在python 画渐变色几何体 python画图渐变颜色_数据可视化之间以均匀间隔选取了200个点,并计算它们的正弦值,再调用plot函数将这200个点的正弦值连成一条曲线,通过plot函数的color参数(也可以简写为c)设置正弦曲线的颜色为绿色——当然,也可以设置为你想要的任意一种颜色。

python 画渐变色几何体 python画图渐变颜色_1024程序员节_02

不过,略有遗憾的是,Matplotlib没有提供直接的方法为这条曲线上的每一个点设置不同的颜色,而这一需求在数据可视化方面却是非常普遍的。比如,在一条变化复杂的曲线上,如果每个点的数值越大颜色越趋近于红色,数值越小颜色越趋近于蓝色,就更容易展示数据的变化规律。

既然没有直接的方法可用,那就变通一下,将这200个点拆分成199条线段,每条线段设置不同的颜色,不就可以实现上面的需求了吗?这样做的确可行,不过需要调用plot函数199次,过程漫长到令人无法忍受,并且更新显示(比如缩放)时也会重复这个漫长的调用过程。

幸运的是,Matplotlib提供了另外一种方法,基本思路也是将这200个点拆分成199条线段,每条线段设置不同的颜色,只是不需要反复调用plot函数,因此速度和单次调用plot函数相差无几。这个方法就是Matplotlib的LineCollection对象。

在使用LineCollection之前,还需要生成199条线段的颜色。下面这个函数实现可数值到颜色的映射,给定一组数据和一个颜色映射方案,即返回每个数据的映射颜色。

import numpy as np
import matplotlib.pyplot as plt

def color_map(data, cmap):
    """数值映射为颜色"""
    
    dmin, dmax = np.nanmin(data), np.nanmax(data)
    cmo = plt.cm.get_cmap(cmap)
    cs, k = list(), 256/cmo.N
    
    for i in range(cmo.N):
        c = cmo(i)
        for j in range(int(i*k), int((i+1)*k)):
            cs.append(c)
    cs = np.array(cs)
    data = np.uint8(255*(data-dmin)/(dmax-dmin))
    
    return cs[data]

实例化LineCollection时,需要提供多条线段的列表(每条线段可以有多个点组成),以及每条线段的颜色组成的列表,也可以设置线宽和线型。如果需要绘制Colorbar的话,还需要为LineCollection指定和数据映射相同的颜色映射方案。完整代码如下。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection

def color_map(data, cmap):
    """数值映射为颜色"""
    
    dmin, dmax = np.nanmin(data), np.nanmax(data)
    cmo = plt.cm.get_cmap(cmap)
    cs, k = list(), 256/cmo.N
    
    for i in range(cmo.N):
        c = cmo(i)
        for j in range(int(i*k), int((i+1)*k)):
            cs.append(c)
    cs = np.array(cs)
    data = np.uint8(255*(data-dmin)/(dmax-dmin))
    
    return cs[data]

x = np.linspace(0, 2*np.pi, 200)
y = np.sin(x)
ps = np.stack((x,y), axis=1)
segments = np.stack((ps[:-1], ps[1:]), axis=1)

cmap = 'viridis' # jet, hsv等也是常用的颜色映射方案
colors = color_map(np.cos(x)[:-1], cmap)
colors = color_map(y[:-1], cmap)
line_segments = LineCollection(segments, colors=colors, linewidths=3, linestyles='solid', cmap=cmap)

fig, ax = plt.subplots()
ax.set_xlim(np.min(x)-0.1, np.max(x)+0.1)
ax.set_ylim(np.min(y)-0.1, np.max(y)+0.1)
ax.add_collection(line_segments)
cb = fig.colorbar(line_segments, cmap='jet')

plt.show()

使用LineCollection绘图时,axis不会自动在x轴和y轴两端留白,通常需要调用set_xlim和set_ylim两个函数设置坐标轴的范围。最终的显示效果如下图所示。

python 画渐变色几何体 python画图渐变颜色_数据可视化_03