python画图|自制渐变柱状图
在前述学习过程中,我们已经通过官网学习了如何绘制渐变的柱状图及其背景。
掌握一门技能的最佳检验方式就是通过实战,因此,本文尝试做一些渐变设计。
前述学习记录可查看链接:
Python画图|渐变背景-CSDN博客
【1】柱状图渐变
在上一篇文章中,由于代码太长,对单个函数的解读不够详细,在本文中可以详细展开。
首先将背景渐变的代码改为注释,原因为:
【a】所有渐变都使用了gradient_image()函数;
【b】gradient_bar()函数通过调用gradient_image()函数画出了渐变的柱状图;
【c】调用gradient_image()函数单独定义了背景渐变。
因此,在不对代码进行修改的前提下,最快速的更改就是把背景渐变的代码消除:
# background image #gradient_image(ax, direction=1, extent=(0, 1, 0, 1), transform=ax.transAxes, #cmap=plt.cm.RdYlGn, cmap_range=(0.2, 0.9), alpha=0.5) #调用了子函数
此时的输出结果为:
图1
由图1可见,坐标轴区域内部已经改为纯色,仅柱状图变成渐变颜色。
然后尝试修改颜色,将柱状图的渐变色改为cmap由plt.cm.Blues_r改为plt.cm.Blues,此时的输出结果为:
图2
对比图1和图2可见,渐变的方向进行了交换。
【2】渐变代码解读
经过追溯, gradient_bar()函数和gradient_image()函数的构造和使用基本上都参考了ax.imshow()函数。
【2.1】ax.imshow()函数
因,在实施渐变以前,有必要先学习ax.imshow()函数:
https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.imshow.html#matplotlib.axes.Axes.imshow
Axes.imshow(X, cmap=None, norm=None, *, aspect=None, interpolation=None, alpha=None, vmin=None, vmax=None, origin=None, extent=None, interpolation_stage=None, filternorm=True, filterrad=4.0, resample=None, url=None, data=None, **kwargs)
ax.imshow()包含参数意义如下:
X:画图数据依据
cmap:颜色参数
norm:标准化工具,将cmap数据缩放到(0,1)范围
aspect:设定坐标轴的长宽比
interpolation:插值设置
alpha:透明度设置
origin:设定数组的起点在左下角还是左上角
extent:边界框
interpolation_stage:插值范围
filternorm:图像粒度调整
filterrad=与差值先关
其余如resample、url、data=None和**kwargs不常用,暂无需关注。
【2.2】gradient_bar()函数
基于此,我们尝试解读下述代码:
def gradient_bar(ax, x, y, width=0.5, bottom=0): #自定义函数 for left, top in zip(x, y): right = left + width #右边等于左边加宽度,这是要逐个排列的意思 gradient_image(ax, extent=(left, right, bottom, top), cmap=plt.cm.Blues##, cmap_range=(0.2, 0.9)
第一行:
def gradient_bar(ax, x, y, width=0.5, bottom=0): #自定义函数
其中的ax,x,y均为外部输入变量, width=0.5, bottom=0为内部已经完成定义的变量。
for函数对x和y组成的组合数组进行取值。
right是内部变量,left+width代表着柱状图不断右移。
gradient_image()函数在此处被直接调用,调用的时候只需要外部输入ax,其余参数如extent、cmap和cmap_range都已经提前完成了赋值。
【2.3】gradient_image()函数
基于前述分析,我们尝试解读下述代码:
# background image gradient_image(ax, direction=1, extent=(0, 1, 0, 1), transform=ax.transAxes, cmap=plt.cm.RdYlGn, cmap_range=(0.2, 0.9), alpha=0.5) #调用了子函数
这里是对gradient_image()函数的直接调用,几乎所有参数都已经解读过,稍有变化的是里面多了一个transform参数,这里的transform=ax.transAxes就是把ax值转化为Axes值 ,顺直坐标轴画直方图的意思。
【3】渐变调控
根据前述分析已经知晓,柱状图渐变和背景渐变可以分别设置,因此,此处尝试消除柱状图渐变,然后恢复背景渐变。
【3.1】柱状图渐变
消除柱状图渐变,最快的方式是将cmap_range的赋值改成一致的即可:
def gradient_bar(ax, x, y, width=0.5, bottom=0): #自定义函数
for left, top in zip(x, y):
right = left + width #右边等于左边加宽度,这是要逐个排列的意思
gradient_image(ax, extent=(left, right, bottom, top),
cmap=plt.cm.Blues, cmap_range=(0.8, 0.8))
此时的输出图像为:
图3
【3.2】背景渐变
消除背景图渐变,最快的方式也是将cmap_range的赋值改成一致的即可:
# background image
gradient_image(ax, direction=1, extent=(0,1,0, 1), transform=ax.transAxes,
cmap=plt.cm.RdYlGn, cmap_range=(0.9, 0.9), alpha=0.5) #调用了子函数
此时的输出图像为:
图4
至此,所有渐变已经消除。
至此的完整代码为:
import matplotlib.pyplot as plt # 引入matplotlib模块画图
import numpy as np # 引入numpy模块做数学计算
np.random.seed(19680801) #定义随机数种子
def gradient_image(ax, direction=0.3, cmap_range=(0, 1), **kwargs): #自定义函数
"""
Draw a gradient image based on a colormap.
Parameters
----------
ax : Axes
The Axes to draw on.
direction : float
The direction of the gradient. This is a number in
range 0 (=vertical) to 1 (=horizontal).
cmap_range : float, float
The fraction (cmin, cmax) of the colormap that should be
used for the gradient, where the complete colormap is (0, 1).
**kwargs
Other parameters are passed on to `.Axes.imshow()`.
In particular, *cmap*, *extent*, and *transform* may be useful.
"""
phi = direction * np.pi / 2 #定义因变量,从np.pi可以看出这是一个角度变量
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 #定义变量a和b
X = a + (b - a) / X.max() * X #定义变量X
im = ax.imshow(X, interpolation='bicubic', clim=(0, 1),
aspect='auto', **kwargs) #定义变量im
return im #返回im
def gradient_bar(ax, x, y, width=0.5, bottom=0): #自定义函数
for left, top in zip(x, y):
right = left + width #右边等于左边加宽度,这是要逐个排列的意思
gradient_image(ax, extent=(left, right, bottom, top),
cmap=plt.cm.Blues, cmap_range=(0.8, 0.8))
fig, ax = plt.subplots()
ax.set(xlim=(0, 10), ylim=(0, 1))
# background image
gradient_image(ax, direction=1, extent=(0,1,0, 1), transform=ax.transAxes,
cmap=plt.cm.RdYlGn, cmap_range=(0.9, 0.9), alpha=0.5) #调用了子函数
N = 10 #定义常量10
x = np.arange(N) + 0.15 #使用随机变量参与运算制造变量x
y = np.random.rand(N) #定义随机矩阵
gradient_bar(ax, x, y, width=0.7) #画随机柱状图
plt.show() #输出图形
【4】坐标轴外背景颜色设置
在前述学习过程中,已经讨论了坐标轴以外的颜色设置,详见下述链接:
python画图|图像背景颜色设置-CSDN博客
此处的渐变仅仅涉及坐标轴内部区域和柱状图本身,基于此,尝试设置坐标轴外部的颜色,修改画图代码为:
fig, ax = plt.subplots(facecolor=(0.6, 0.5,0.9))
此时的输出结果为:
图5
由图5可见,外部背景、坐标轴内都有了颜色。
此时的完整代码为:
import matplotlib.pyplot as plt # 引入matplotlib模块画图
import numpy as np # 引入numpy模块做数学计算
np.random.seed(19680801) #定义随机数种子
def gradient_image(ax, direction=0.3, cmap_range=(0, 1), **kwargs): #自定义函数
"""
Draw a gradient image based on a colormap.
Parameters
----------
ax : Axes
The Axes to draw on.
direction : float
The direction of the gradient. This is a number in
range 0 (=vertical) to 1 (=horizontal).
cmap_range : float, float
The fraction (cmin, cmax) of the colormap that should be
used for the gradient, where the complete colormap is (0, 1).
**kwargs
Other parameters are passed on to `.Axes.imshow()`.
In particular, *cmap*, *extent*, and *transform* may be useful.
"""
phi = direction * np.pi / 2 #定义因变量,从np.pi可以看出这是一个角度变量
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 #定义变量a和b
X = a + (b - a) / X.max() * X #定义变量X
im = ax.imshow(X, interpolation='bicubic', clim=(0, 1),
aspect='auto', **kwargs) #定义变量im
return im #返回im
def gradient_bar(ax, x, y, width=0.5, bottom=0): #自定义函数
for left, top in zip(x, y):
right = left + width #右边等于左边加宽度,这是要逐个排列的意思
gradient_image(ax, extent=(left, right, bottom, top),
cmap=plt.cm.Blues, cmap_range=(0.8, 0.8))
fig, ax = plt.subplots(facecolor=(0.6, 0.5,0.9)) #设置坐标轴外区域颜色
ax.set(xlim=(0, 10), ylim=(0, 1))
# background image
gradient_image(ax, direction=1, extent=(0,1,0, 1), transform=ax.transAxes,
cmap=plt.cm.RdYlGn, cmap_range=(0.9, 0.9), alpha=0.5) #调用了子函数
N = 10 #定义常量10
x = np.arange(N) + 0.15 #使用随机变量参与运算制造变量x
y = np.random.rand(N) #定义随机矩阵
gradient_bar(ax, x, y, width=0.7) #画随机柱状图
plt.show() #输出图形
【5】自主渐变设置
在前述学习的基础上,给所有区域山上色,并对坐标轴内部区域进行渐变设置,并设置图名为“Gradient Color”。
完整代码为:
import matplotlib.pyplot as plt # 引入matplotlib模块画图
import numpy as np # 引入numpy模块做数学计算
np.random.seed(19680801) #定义随机数种子
def gradient_image(ax, direction=0.3, cmap_range=(0, 1), **kwargs): #自定义函数
"""
Draw a gradient image based on a colormap.
Parameters
----------
ax : Axes
The Axes to draw on.
direction : float
The direction of the gradient. This is a number in
range 0 (=vertical) to 1 (=horizontal).
cmap_range : float, float
The fraction (cmin, cmax) of the colormap that should be
used for the gradient, where the complete colormap is (0, 1).
**kwargs
Other parameters are passed on to `.Axes.imshow()`.
In particular, *cmap*, *extent*, and *transform* may be useful.
"""
phi = direction * np.pi / 2 #定义因变量,从np.pi可以看出这是一个角度变量
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 #定义变量a和b
X = a + (b - a) / X.max() * X #定义变量X
im = ax.imshow(X, interpolation='bicubic', clim=(0, 1),
aspect='auto', **kwargs) #定义变量im
return im #返回im
def gradient_bar(ax, x, y, width=0.5, bottom=0): #自定义函数
for left, top in zip(x, y):
right = left + width #右边等于左边加宽度,这是要逐个排列的意思
gradient_image(ax, extent=(left, right, bottom, top),
cmap=plt.cm.Blues, cmap_range=(0.2, 0.8))
fig, ax = plt.subplots(facecolor=(0.6, 0.5,0.9)) #设置坐标轴外区域颜色
ax.set(xlim=(0, 10), ylim=(0, 1))
# background image
gradient_image(ax, direction=1, extent=(0,1,0, 1), transform=ax.transAxes,
cmap=plt.cm.RdYlGn, cmap_range=(0.1, 0.9), alpha=0.5) #调用了子函数
N = 10 #定义常量10
x = np.arange(N) + 0.15 #使用随机变量参与运算制造变量x
y = np.random.rand(N) #定义随机矩阵
gradient_bar(ax, x, y, width=0.7) #画随机柱状图
ax.set_title('Gradient Color') #设置图名
plt.show() #输出图形
输出图形为:
图6
由图6可见,坐标轴内部的柱状图和背景颜色均渐变,坐标轴外的区域则是纯色。
【6】总结
学习了柱状图、坐标轴区域内部背景颜色的渐变设计,以及为坐标轴外部区域增添颜色。