matplotlib bar()实现多组数据并列柱状图通用简便创建方法


Posted in Python onFebruary 24, 2021

在使用柱状图时,经常遇到需要多组数据进行比较的情况。
绘制单个数据系列的柱形图比较简单,多组数据柱状图绘制的关键有三点:

  • 多次调用bar()函数即可在同一子图中绘制多组柱形图。
  • 为了防止柱子重叠,每个柱子在x轴上的位置需要依次递增,如果柱子紧挨,这个距离即柱子宽度。
  • 为了使刻度标签居中,需要调整x轴刻度标签的位置。

由上述可知,多组数据并列柱状图需要计算柱子x轴上的位置和x轴刻度标签。
因此,有两种实现方案:

  • x轴刻度标签位置固定,根据x轴刻度计算每个柱子的宽度
  • 每个柱子的宽度固定,计算x轴刻度标签位置,使之居中

下面使用第一种方法演示两组数据、三组数据、四组数据的并列柱状图。
使用方法一、方法二演示通用多组并列柱状图的创建方法。

两组数据、三组数据、四组数据的并列柱状图

matplotlib bar()实现多组数据并列柱状图通用简便创建方法

import matplotlib
import matplotlib.pyplot as plt
import numpy as np

plt.figure(figsize=(13, 4))
# 构造x轴刻度标签、数据
labels = ['G1', 'G2', 'G3', 'G4', 'G5']
first = [20, 34, 30, 35, 27]
second = [25, 32, 34, 20, 25]
third = [21, 31, 37, 21, 28]
fourth = [26, 31, 35, 27, 21]

# 两组数据
plt.subplot(131)
x = np.arange(len(labels)) # x轴刻度标签位置
width = 0.25 # 柱子的宽度
# 计算每个柱子在x轴上的位置,保证x轴刻度标签居中
# x - width/2,x + width/2即每组数据在x轴上的位置
plt.bar(x - width/2, first, width, label='1')
plt.bar(x + width/2, second, width, label='2')
plt.ylabel('Scores')
plt.title('2 datasets')
# x轴刻度标签位置不进行计算
plt.xticks(x, labels=labels)
plt.legend()
# 三组数据
plt.subplot(132)
x = np.arange(len(labels)) # x轴刻度标签位置
width = 0.25 # 柱子的宽度
# 计算每个柱子在x轴上的位置,保证x轴刻度标签居中
# x - width,x, x + width即每组数据在x轴上的位置
plt.bar(x - width, first, width, label='1')
plt.bar(x, second, width, label='2')
plt.bar(x + width, third, width, label='3')
plt.ylabel('Scores')
plt.title('3 datasets')
# x轴刻度标签位置不进行计算
plt.xticks(x, labels=labels)
plt.legend()
# 四组数据
plt.subplot(133)
x = np.arange(len(labels)) # x轴刻度标签位置
width = 0.2 # 柱子的宽度
# 计算每个柱子在x轴上的位置,保证x轴刻度标签居中
plt.bar(x - 1.5*width, first, width, label='1')
plt.bar(x - 0.5*width, second, width, label='2')
plt.bar(x + 0.5*width, third, width, label='3')
plt.bar(x + 1.5*width, fourth, width, label='4')
plt.ylabel('Scores')
plt.title('4 datasets')
# x轴刻度标签位置不进行计算
plt.xticks(x, labels=labels)
plt.legend()

plt.show()

通用多组并列柱状图的简便创建方法

上面的示例比较简易,有一些问题没有考虑。为了便于重复使用,下面的通用方法可调整x轴标签刻度步长、每组柱子的总宽度、每组柱子之间的间隙、组与组之间的间隙。

matplotlib bar()实现多组数据并列柱状图通用简便创建方法

方法一

import matplotlib
import matplotlib.pyplot as plt
import numpy as np

label = ['G1', 'G2', 'G3', 'G4', 'G5']
first = [20, 34, 30, 35, 27]
second = [25, 32, 34, 20, 25]
third = [21, 31, 37, 21, 28]
fourth = [26, 31, 35, 27, 21]
data = [first, second, third, fourth]


def create_multi_bars(labels, datas, tick_step=1, group_gap=0.2, bar_gap=0):
  '''
  labels : x轴坐标标签序列
  datas :数据集,二维列表,要求列表每个元素的长度必须与labels的长度一致
  tick_step :默认x轴刻度步长为1,通过tick_step可调整x轴刻度步长。
  group_gap : 柱子组与组之间的间隙,最好为正值,否则组与组之间重叠
  bar_gap :每组柱子之间的空隙,默认为0,每组柱子紧挨,正值每组柱子之间有间隙,负值每组柱子之间重叠
  '''
  # ticks为x轴刻度
  ticks = np.arange(len(labels)) * tick_step
  # group_num为数据的组数,即每组柱子的柱子个数
  group_num = len(datas)
  # group_width为每组柱子的总宽度,group_gap 为柱子组与组之间的间隙。
  group_width = tick_step - group_gap
  # bar_span为每组柱子之间在x轴上的距离,即柱子宽度和间隙的总和
  bar_span = group_width / group_num
  # bar_width为每个柱子的实际宽度
  bar_width = bar_span - bar_gap
  # baseline_x为每组柱子第一个柱子的基准x轴位置,随后的柱子依次递增bar_span即可
  baseline_x = ticks - (group_width - bar_span) / 2
  for index, y in enumerate(datas):
    plt.bar(baseline_x + index*bar_span, y, bar_width)
  plt.ylabel('Scores')
  plt.title('multi datasets')
  # x轴刻度标签位置与x轴刻度一致
  plt.xticks(ticks, labels)
  plt.show()
  

create_multi_bars(label, data, bar_gap=0.1)

方法二

import matplotlib
import matplotlib.pyplot as plt
import numpy as np

label = ['G1', 'G2', 'G3', 'G4', 'G5']
first = [20, 34, 30, 35, 27]
second = [25, 32, 34, 20, 25]
third = [21, 31, 37, 21, 28]
fourth = [26, 31, 35, 27, 21]
data = [first, second, third, fourth]


def create_multi_bars(labels, datas, tick_step=1, group_gap=0.2, bar_gap=0):
  '''
  labels : x轴坐标标签序列
  datas :数据集,二维列表,要求列表每个元素的长度必须与labels的长度一致
  tick_step :默认x轴刻度步长为1,通过tick_step可调整x轴刻度步长。
  group_gap : 柱子组与组之间的间隙,最好为正值,否则组与组之间重叠
  bar_gap :每组柱子之间的空隙,默认为0,每组柱子紧挨,正值每组柱子之间有间隙,负值每组柱子之间重叠
  '''
  # x为每组柱子x轴的基准位置
  x = np.arange(len(labels)) * tick_step
  # group_num为数据的组数,即每组柱子的柱子个数
  group_num = len(datas)
  # group_width为每组柱子的总宽度,group_gap 为柱子组与组之间的间隙。
  group_width = tick_step - group_gap
  # bar_span为每组柱子之间在x轴上的距离,即柱子宽度和间隙的总和
  bar_span = group_width / group_num
  # bar_width为每个柱子的实际宽度
  bar_width = bar_span - bar_gap
  # 绘制柱子
  for index, y in enumerate(datas):
    plt.bar(x + index*bar_span, y, bar_width)
  plt.ylabel('Scores')
  plt.title('multi datasets')
  # ticks为新x轴刻度标签位置,即每组柱子x轴上的中心位置
  ticks = x + (group_width - bar_span) / 2
  plt.xticks(ticks, labels)
  plt.show()

create_multi_bars(label, data[:3], bar_gap=0.1)
Python 相关文章推荐
python利用elaphe制作二维条形码实现代码
May 25 Python
python代码检查工具pylint 让你的python更规范
Sep 05 Python
python使用win32com在百度空间插入html元素示例
Feb 20 Python
详解Python中的各种函数的使用
May 24 Python
Python实现自动添加脚本头信息的示例代码
Sep 02 Python
使用Python对Csv文件操作实例代码
May 12 Python
pandas DataFrame 交集并集补集的实现
Jun 24 Python
python实现集中式的病毒扫描功能详解
Jul 09 Python
利用Python的turtle库绘制玫瑰教程
Nov 23 Python
Python 日期与时间转换的方法
Aug 01 Python
如何快速理解python的垃圾回收机制
Sep 01 Python
python3访问字典里的值实例方法
Nov 18 Python
pandas apply使用多列计算生成新的列实现示例
Feb 24 #Python
pandas map(),apply(),applymap()区别解析
Feb 24 #Python
Python的Tqdm模块实现进度条配置
Feb 24 #Python
详解pandas apply 并行处理的几种方法
Feb 24 #Python
python自动生成sql语句的脚本
Feb 24 #Python
Django与AJAX实现网页动态数据显示的示例代码
Feb 24 #Python
一文读懂python Scrapy爬虫框架
Feb 24 #Python
You might like
PHP网页游戏学习之Xnova(ogame)源码解读(一)
2014/06/23 PHP
PHP实现事件机制实例分析
2015/06/26 PHP
php用户注册信息验证正则表达式
2015/11/12 PHP
laravel框架创建授权策略实例分析
2019/11/22 PHP
通过jquery的$.getJSON做一个跨域ajax请求试验
2011/05/03 Javascript
js正则表达exec与match的区别说明
2014/01/29 Javascript
JS弹出层单纯的绝对定位居中示例代码
2014/02/18 Javascript
JS 排序输出实现table行号自增前端动态生成的tr
2014/08/13 Javascript
jQuery+css3实现文字跟随鼠标的上下抖动
2015/07/31 Javascript
js中flexible.js实现淘宝弹性布局方案
2020/06/23 Javascript
javascript每日必学之封装
2016/02/23 Javascript
requireJS使用指南
2016/04/27 Javascript
Bootstrap modal 多弹窗之叠加显示不出弹窗问题的解决方案
2017/02/23 Javascript
BootstrapValidator实现注册校验和登录错误提示效果
2017/03/10 Javascript
javascript基于定时器实现进度条功能实例
2017/10/13 Javascript
VUE + UEditor 单图片跨域上传功能的实现方法
2018/02/08 Javascript
jQuery+Datatables实现表格批量删除功能【推荐】
2018/10/24 jQuery
JavaScript实现动态留言板
2020/03/16 Javascript
jQuery实现的分页插件完整示例
2020/05/26 jQuery
详解Vue中的MVVM原理和实现方法
2020/07/15 Javascript
[17:36]VG战队纪录片
2014/08/21 DOTA
用Python从零实现贝叶斯分类器的机器学习的教程
2015/03/31 Python
Python搭建FTP服务器的方法示例
2018/01/19 Python
python路径的写法及目录的获取方式
2019/12/26 Python
Python3 filecmp模块测试比较文件原理解析
2020/03/23 Python
python基于opencv 实现图像时钟
2021/01/04 Python
解决pytorch 的state_dict()拷贝问题
2021/03/03 Python
Ever New美国:澳大利亚领先的女装时尚品牌
2019/11/28 全球购物
致800米运动员广播稿
2014/02/16 职场文书
《云雀的心愿》教学反思
2014/02/25 职场文书
城市创卫标语
2014/06/17 职场文书
营销与策划专业求职信
2014/06/20 职场文书
羽毛球社团活动总结
2014/06/27 职场文书
个人贷款收入证明
2014/10/26 职场文书
维稳承诺书
2015/01/20 职场文书
满月酒邀请函
2015/01/30 职场文书