扇形图自定义色彩条
# 代码均为本人硕士期间绘制,为便于阅读和改进尽可能逐行添加了注释。
# 部分代码可能写的较繁琐,如果有更简洁的写法欢迎留言!
# 感谢在我科研绘图过程中提供帮助的各位博主!
# 导包
import matplotlib.pyplot as plt
from matplotlib import rcParams
# 设置配置文件
config = {
# 衬线字体(衬线字体, 宋体和Times New Roman属于这类字体)
"font.family": 'serif',
# matplotlib渲染数学字体时使用的字体,和Times New Roman差别不大
"mathtext.fontset": 'stix',
# 设置绘图时全局字体为宋体(SimSun)
"font.serif": ['SimSun'],
}
# 修改运行时配置参数的方法(Matplotlib使用matplotlibrc配置文件来自定义图形的各种属性,称之为rc配置或rc参数(rcParams))
rcParams.update(config)
# 为每个扇形提供颜色,颜色顺序与排序后的x顺序对应
colors = ['#c4cc38', '#ebe12a', '#ebe12a', '#ebe12a', '#eab026', '#e3852b', '#d85d2a', '#ce2626']
def draw_pic(x, y):
# 绘制饼图
'''
plt.pie(x, explode=None, labels=None, colors=None, autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1,
startangle=0, radius=1, counterclock=True, wedgeprops=None, textprops=None, center=0, 0, frame=False,
rotatelabels=False, *, normalize=None, data=None)
传入的参数y为每个扇形的占比数组;
labels为每个扇形提供标签的字符串序列;
autopct如果是一个格式字符串,标签将是fmt % pct。如果它是一个函数,它将被调用。在代码中%0.1f%%表示保留1位小数;
colors为每个扇形提供颜色;
wedgeprops设置饼图内外边界的属性,如边界线的粗细、颜色等。在代码中,我们设置边框为黑色;
textprops设置饼图中文本的属性,如字体大小、颜色等。在代码中,我们设置字号为12,字体为新罗马;
labeldistance设置各扇形标签(图例)与圆心的距离。
'''
plt.pie(y, labels=x, autopct="%0.1f%%", colors=colors, wedgeprops={'edgecolor': "black"},
textprops={'fontsize': 12, 'fontproperties': 'Times New Roman'}, labeldistance=1.05)
# 关闭坐标轴
plt.axis('off')
# Matplotlib自定义添加colorbar
# 添加子图plt.axis([a, b, c, d]) 设置x轴的范围为[a, b],y轴的范围为[c, d]
cax = plt.axes([0.805, 0.25, 0.03, 0.5])
'''
fill_between用于在两条曲线间填充颜色
fill_between(y, x1, x2=0, where=None, step=None, interpolate=False,
data=None, **kwargs)
y:表示y轴坐标的序列;
x1:表示第一条曲线的x轴坐标;
x2:表示第二条曲线的x轴坐标;
·where:布尔值,表示要填充区域的条件。
'''
cax.fill_between([0, 0.5], 0.5, color=colors[7])
cax.fill_between([0, 0.5], 0.5, 1, color=colors[6])
cax.fill_between([0, 0.5], 1, 1.5, color=colors[5])
cax.fill_between([0, 0.5], 1.5, 2, color=colors[4])
cax.fill_between([0, 0.5], 2, 2.5, color=colors[3])
cax.fill_between([0, 0.5], 2.5, 3, color=colors[0])
# 设置y轴正向显示范围
cax.set_ylim(0, 3)
# 设置x轴和y轴刻度
cax.set_xticks([])
cax.set_yticks([0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0])
cax.set_yticklabels(['高频', '', '', ' ', '', '', '低频'], fontsize=12)
# 将y轴的数值显示在右边
cax.yaxis.tick_right()
# 获取y轴所有刻度信息
yticks = cax.yaxis.get_major_ticks()
# # 隐藏第1~第5个刻线
yticks[1].set_visible(False)
yticks[2].set_visible(False)
yticks[3].set_visible(False)
yticks[4].set_visible(False)
yticks[5].set_visible(False)
# 存储为SVG格式(矢量图不失真),bbox_inches='tight', pad_inches=0可以去除图片的白边
plt.savefig('CTU-13 场景特征频数.svg', bbox_inches='tight', pad_inches=0)
plt.show()
if __name__ == '__main__':
# 待统计序列
feature_list = ['IRC', 'SPAM', 'CF', 'IRC', 'SPAM', 'CF', 'IRC', 'PS', 'US', 'IRC', 'DDoS', 'US', 'SPAM', 'PS',
'HTTP',
'PS', 'HTTP', 'PS', 'IRC', 'SPAM', 'CF', 'PS', 'IRC', 'DDoS', 'US', 'IRC', 'DDoS', 'US', 'P2P',
'SPAM',
'PS', 'HTTP']
# 统计待统计序列中每类的频数,存放在字典a中
a = {}
for i in feature_list:
a[i] = feature_list.count(i)
# print(a)
# 字典按值排序,将排序后的字典按照key和value的对应关系存放在a_order中
a_order = sorted(a.items(), key=lambda x: x[1])
# print(a_order)
# 分别将a_order中每个元组的第一项和第二项,存放在x,y中,即x为每类名称,y为对应的频数
x = []
y = []
for i in range(len(a_order)):
x.append(a_order[i][0])
y.append(a_order[i][1])
# print(x, y)
# 绘图
draw_pic(x, y)
