matplotlib 柱状图之渐变色设置
-
matplotlib中,在用bar或者barh绘制柱状图时,发现加入cmap是不管用的,不支持这个关键字,而且网上找了许久,也没有发现有类似功能,最后参考了官网案例。
-
渐变色的设置,其主要就是获取边界,然后向边界内部填充颜色就好啦,因此函数需要获取绘制的ax对象,获取边界,获取渐变色的cmap,以及cmap中的取值范围,以及一些其他的参数
-
渐变色对象:一是背景色;二是柱子填充颜色。 OK here we go!
首先来一组随机数据:
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(20191001)
length = 5
xmin, xmax = 0, length
ymin, ymax = 0, 1
设置图像大小:
fig, ax = plt.subplots()
ax.set(xlim=(xmin, xmax), ylim=(ymin, ymax), autoscale_on=False)
接下来就是要对图像中填入渐变色了,按照上面的分析,需要对象,边界,渐变方向, cmap与范围,其余参数等等,
def gradient(ax, boundary, extent=0.3, cmap_range=(0, 1), **kwargs):
v = np.array([np.cos(direction * np.pi / 2), np.sin(direction * np.pi / 2)])
X = np.array([[v @ [1, 0], v @ [1, 1]],
[v @ [0, 0], v @ [0, 1]]])
a, b = cmap_range
X = a + (b - a) / X.max() * X
im = ax.imshow(X, extent=extent, interpolation='bicubic',
vmin=0, vmax=1, **kwargs)
return im
其中,核心为调用imshow函数,所以也需要继承其中的kwargs。这里return是为了方便以后调用。
进而基于这个函数,我们可以填充每个柱子:,只要往上面的自定义函数里面传入边界与柱子宽度,以及渐变色即可,
def gradient_bar(ax, x, y, width=0.3, bottom=0):
for left, top in zip(x, y):
right = left + width
gradient(ax, extent=(left, right, bottom, top),
cmap=plt.cm.Reds, cmap_range=(0.8, 0))
不需要return。
这样完整的代码就是如下:
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(20191001)
def gradient(ax, boundary, direction=0.3, cmap_range=(0, 1), **kwargs):
phi = direction * np.pi / 2
v = np.array([np.cos(phi), np.sin(phi)])
X = np.array([[v @ [1, 0], v @ [1, 1]],
[v @ [0, 0], v @ [0, 1]]])
a, b = cmap_range
X = a + (b - a) / X.max() * X
im = ax.imshow(X, extent=boundary, interpolation='bicubic',
vmin=0, vmax=1, **kwargs)
return im
def gradient_bar(ax, x, y, width=0.3, bottom=0):
for left, top in zip(x, y):
right = left + width
gradient(ax, boundary=(left, right, bottom, top),
cmap=plt.cm.Reds, cmap_range=(0.8, 0), direction = 0.3)
length = 5
xmin, xmax = 0, length
ymin, ymax = 0, 1
fig, ax = plt.subplots()
ax.set(xlim=(xmin, xmax), ylim=(ymin, ymax), autoscale_on=False)
x = np.arange(length) + 0.2
y = np.random.rand(length)
# bar image
gradient_bar(ax, x, y, width=0.3)
ax.set_aspect('auto')
plt.show()
完事~