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使用MySQLdb for Python操作数据库教程
Oct 11 Python
浅谈Python的垃圾回收机制
Dec 17 Python
python自动重试第三方包retrying模块的方法
Apr 24 Python
python pandas修改列属性的方法详解
Jun 09 Python
python实现多人聊天室
Mar 31 Python
基于python if 判断选择结构的实例详解
May 06 Python
python实现差分隐私Laplace机制详解
Nov 25 Python
win10安装tensorflow-gpu1.8.0详细完整步骤
Jan 20 Python
TensorFlow keras卷积神经网络 添加L2正则化方式
May 22 Python
如何使用python记录室友的抖音在线时间
Jun 29 Python
基于Python pyecharts实现多种图例代码解析
Aug 10 Python
Python生成九宫格图片的示例代码
Apr 14 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 setTime 设置当前时间的代码
2012/08/27 PHP
php switch语句多个值匹配同一代码块的实现
2014/03/03 PHP
Dojo 学习笔记入门篇 First Dojo Example
2009/11/15 Javascript
jquery 面包屑导航 具体实现
2013/06/05 Javascript
JS求平均值的小例子
2013/11/29 Javascript
JQuery插入DOM节点的方法
2015/06/11 Javascript
indexedDB bootstrap angularjs之 MVC DOMO (应用示例)
2016/06/20 Javascript
vue2.0结合DataTable插件实现表格动态刷新的方法详解
2017/03/17 Javascript
JS简单实现获取元素的封装操作示例
2017/04/07 Javascript
webpack实现热加载自动刷新的方法
2017/07/30 Javascript
vue+node+webpack环境搭建教程
2017/11/05 Javascript
如何使用 vue + d3 画一棵树
2018/12/03 Javascript
vue实现的微信机器人聊天功能案例【附源码下载】
2019/02/18 Javascript
laravel-admin 与 vue 结合使用实例代码详解
2019/06/04 Javascript
Python ljust rjust center输出
2008/09/06 Python
Python 字典(Dictionary)操作详解
2014/03/11 Python
介绍Python中的一些高级编程技巧
2015/04/02 Python
python脚本设置超时机制系统时间的方法
2016/02/21 Python
简单实现python收发邮件功能
2018/01/05 Python
python的re正则表达式实例代码
2018/01/24 Python
python 中文件输入输出及os模块对文件系统的操作方法
2018/08/27 Python
对Python subprocess.Popen子进程管道阻塞详解
2018/10/29 Python
python 使用re.search()筛选后 选取部分结果的方法
2018/11/28 Python
python实现生成字符串大小写字母和数字的各种组合
2019/01/01 Python
Python使用修饰器进行异常日志记录操作示例
2019/03/19 Python
Python3使用Matplotlib 绘制精美的数学函数图形
2019/04/11 Python
处理python中多线程与多进程中的数据共享问题
2019/07/28 Python
win10下python3.8的PIL库安装过程
2020/06/08 Python
keras 回调函数Callbacks 断点ModelCheckpoint教程
2020/06/18 Python
python/golang 删除链表中的元素
2020/09/14 Python
聪明的粉丝购买门票的地方:TickPick
2018/03/09 全球购物
《阳光》教学反思
2014/02/23 职场文书
小学端午节活动方案
2014/03/13 职场文书
师范类求职信
2014/06/21 职场文书
乡镇防汛工作汇报
2014/10/28 职场文书
python3实现无权最短路径的方法
2021/05/12 Python