Python matplotlib读取excel数据并用for循环画多个子图subplot操作


Posted in Python onJuly 14, 2020

读取excel数据需要用到xlrd模块,在命令行运行下面命令进行安装

pip install xlrd

表格内容大致如下,有若干sheet,每个sheet记录了同一所学校的所有学生成绩,分为语文、数学、英语、综合、总分

考号 姓名 班级 学校 语文 数学 英语 综合 总分
... ... ... ... 136 136 100 57 429
... ... ... ... 128 106 70 54 358
... ... ... ... 110.5 62 92 44 308.5

画多张子图需要用到subplot函数

subplot(nrows, ncols, index, **kwargs)

想要在一张画布上按如下格式画多张子图

语文 --- 数学

英语 --- 综合

----- 总分 ----

需要用的subplot参数分别为

subplot(321) --- subplot(322)

subplot(323) --- subplot(324)

subplot(313)

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from xlrd import open_workbook as owb
import matplotlib.pyplot as plt
#import matplotlib.colors as colors
#from matplotlib.ticker import MultipleLocator, FormatStrFormatter, FuncFormatter
import numpy as np
 
districts=[] # 存储各校名称--对应于excel表格的sheet名
data_index = 0
new_colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728',
    '#9467bd', '#8c564b', '#e377c2', '#7f7f7f',
    '#bcbd22', '#17becf']
wb = owb('raw_data.xlsx') # 数据文件
active_districts = ['二小','一小','四小'] ## 填写需要画哪些学校的,名字需要与表格内一致
avg_yuwen = []
avg_shuxue = []
avg_yingyu = []
avg_zonghe = []
avg_total = []
'按页数依次读取表格数据作为Y轴参数'
for s in wb.sheets():
 #以下两行用于控制是否全部绘图,还是只绘选择的区
 #if s.name not in active_districts:
  # continue
 print('Sheet: ', s.name)
 districts.append(s.name)
 avg_score = 0
 yuwen = 0
 shuxue = 0
 yingyu = 0
 zonghe = 0
 zongfen = 0
 total_student = 0
 for row in range(1,s.nrows):
  total_student += 1
  #读取各科成绩并计算平均分
  yuwen = yuwen + (s.cell(row, 4).value - yuwen)/total_student # 语文
  shuxue = shuxue + (s.cell(row, 5).value - shuxue) / total_student # 数学
  yingyu = yingyu + (s.cell(row, 6).value - yingyu) / total_student # 英语
  zonghe = zonghe + (s.cell(row, 7).value - zonghe) / total_student # 综合
  zongfen = zongfen + (s.cell(row, 8).value - zongfen) / total_student # 总分
 avg_yuwen.append(yuwen)
 avg_shuxue.append(shuxue)
 avg_yingyu.append(yingyu)
 avg_zonghe.append(zonghe)
 avg_total.append(zongfen)
 data_index += 1
 
print('开始画图...')
plt.rcParams['font.sans-serif']=['SimHei'] # 中文支持
plt.rcParams['axes.unicode_minus']=False # 中文支持
figsize = 11,14
fig = plt.figure(figsize=figsize)
fig.suptitle('各校各科成绩平均分统计',fontsize=18)
my_x=np.arange(len(districts))
width=0.5
 
ax1 = plt.subplot(321)
#total_width=width*(len(districts))
b = ax1.bar(my_x , avg_yuwen, width, tick_label=districts, align='center', color=new_colors)
for i in range(0,len(avg_yuwen)):
 ax1.text(my_x[i], avg_yuwen[i], '%.2f' % (avg_yuwen[i]), ha='center', va='bottom',fontsize=10)
ax1.set_title(u'语文')
ax1.set_ylabel(u"平均分")
ax1.set_ylim(60, 130)
 
ax2 = plt.subplot(322)
ax2.bar(my_x, avg_shuxue, width, tick_label=districts, align='center', color=new_colors)
for i in range(0, len(avg_shuxue)):
 ax2.text(my_x[i], avg_shuxue[i], '%.2f' %(avg_shuxue[i]), ha='center', va='bottom', fontsize=10)
ax2.set_title(u'数学')
ax2.set_ylabel(u'平均分')
ax2.set_ylim(50,120)
 
ax3 = plt.subplot(323)
b = ax3.bar(my_x , avg_yingyu, width, tick_label=districts, align='center', color=new_colors)
for i in range(0,len(avg_yingyu)):
 ax3.text(my_x[i], avg_yingyu[i], '%.2f' % (avg_yingyu[i]), ha='center', va='bottom',fontsize=10)
ax3.set_title(u'英语')
ax3.set_ylabel(u"平均分")
ax3.set_ylim(30, 100)
 
ax4 = plt.subplot(324)
b = ax4.bar(my_x , avg_zonghe, width, tick_label=districts, align='center', color=new_colors)
for i in range(0,len(avg_zonghe)):
 ax4.text(my_x[i], avg_zonghe[i], '%.2f' % (avg_zonghe[i]), ha='center', va='bottom',fontsize=10)
ax4.set_title(u'综合')
ax4.set_ylabel(u"平均分")
ax4.set_ylim(0, 60)
 
ax5 = plt.subplot(313)
total_width=width*(len(districts))
b = ax5.bar(my_x , avg_total, width, tick_label=districts, align='center', color=new_colors)
for i in range(0,len(avg_total)):
 ax5.text(my_x[i], avg_total[i], '%.2f' % (avg_total[i]), ha='center', va='bottom',fontsize=10)
ax5.set_title(u'总分')
ax5.set_ylabel(u"平均分")
ax5.set_ylim(250, 400)
 
plt.savefig('avg.png')
plt.show()

Python matplotlib读取excel数据并用for循环画多个子图subplot操作

这样虽然能画出来,但是需要手动写每个subplot的代码,代码重复量太大,能不能用for循环的方式呢?

继续尝试,

先整理出for循环需要的不同参数

avg_scores = [] # 存储各科成绩,2维list
subjects = ['语文','数学','英语','综合','总分'] #每个子图的title
plot_pos = [321,322,323,324,313] # 每个子图的位置
y_lims = [(60,130), (50,120), (30,100), (0,60), (200,400)] # 每个子图的ylim参数

数据读取的修改比较简单,但是到画图时,如果还用 ax = plt.subplots(plot_pos[pos])方法的话,会报错

Traceback (most recent call last):
 File "...xxx.py", line 66, in <module>
 b = ax.bar(my_x , y_data, width, tick_label=districts, align='center', color=new_colors) # 画柱状图
AttributeError: 'tuple' object has no attribute 'bar'

搜索一番,没找到合适的答案,想到可以换fig.add_subplot(plot_pos[pos]) 试一试,结果成功了,整体代码如下

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from xlrd import open_workbook as owb
import matplotlib.pyplot as plt
#import matplotlib.colors as colors
#from matplotlib.ticker import MultipleLocator, FormatStrFormatter, FuncFormatter
import numpy as np
 
districts=[] # 存储各校名称--对应于excel表格的sheet名
total_stu=[] # 存储各区学生总数
data_index = 0
new_colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728',
    '#9467bd', '#8c564b', '#e377c2', '#7f7f7f',
    '#bcbd22', '#17becf']
wb = owb('raw_data.xlsx') # 数据文件
active_districts = ['BY','二小','一小','WR','四小'] ## 填写需要画哪些学校的,名字需要与表格内一致
avg_scores = [] # 存储各科成绩,2维list
subjects = ['语文','数学','英语','综合','总分'] #每个子图的title
plot_pos = [321,322,323,324,313] # 每个子图的位置
y_lims = [(60,130), (50,120), (30,100), (0,60), (200,400)] # 每个子图的ylim参数
 
'按页数依次读取表格数据作为Y轴参数'
for s in wb.sheets():
 #以下两行用于控制是否全部绘图,还是只绘选择的区
 #if s.name not in active_districts:
  # continue
 print('Sheet: ', s.name)
 districts.append(s.name)
 avg_scores.append([])
 yuwen = 0
 shuxue = 0
 yingyu = 0
 zonghe = 0
 zongfen = 0
 total_student = 0
 for row in range(1,s.nrows):
  total_student += 1
  #tmp = s.cell(row,4).value
  yuwen = yuwen + (s.cell(row, 4).value - yuwen)/total_student # 语文
  shuxue = shuxue + (s.cell(row, 5).value - shuxue) / total_student # 数学
  yingyu = yingyu + (s.cell(row, 6).value - yingyu) / total_student # 英语
  zonghe = zonghe + (s.cell(row, 7).value - zonghe) / total_student # 综合
  zongfen = zongfen + (s.cell(row, 8).value - zongfen) / total_student # 总分
 avg_scores[data_index].append(yuwen)
 avg_scores[data_index].append(shuxue)
 avg_scores[data_index].append(yingyu)
 avg_scores[data_index].append(zonghe)
 avg_scores[data_index].append(zongfen)
 data_index += 1
 
print('开始画图...')
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
figsize = 11,14
fig = plt.figure(figsize=figsize)
fig.suptitle('各校各科成绩平均分统计',fontsize=18)
my_x=np.arange(len(districts))
width=0.5
 
print(avg_scores)
for pos in np.arange(len(plot_pos)):
 #ax = plt.subplots(plot_pos[pos])
 ax = fig.add_subplot(plot_pos[pos]) # 如果用ax = plt.subplots会报错'tuple' object has no attribute 'bar'
 y_data = [x[pos] for x in avg_scores] # 按列取数据
 print(y_data)
 b = ax.bar(my_x , y_data, width, tick_label=districts, align='center', color=new_colors) # 画柱状图
 for i in np.arange(len(y_data)):
  ax.text(my_x[i], y_data[i], '%.2f' % (y_data[i]), ha='center', va='bottom',fontsize=10) # 添加文字
 ax.set_title(subjects[pos])
 ax.set_ylabel(u"平均分")
 ax.set_ylim(y_lims[pos])
 
plt.savefig('jh_avg_auto.png')
plt.show()

和之前的结果一样,能找到唯一一处细微差别嘛

Python matplotlib读取excel数据并用for循环画多个子图subplot操作

以上这篇Python matplotlib读取excel数据并用for循环画多个子图subplot操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中让MySQL查询结果返回字典类型的方法
Aug 22 Python
python结合API实现即时天气信息
Jan 19 Python
基于Django用户认证系统详解
Feb 21 Python
python中字符串变二维数组的实例讲解
Apr 03 Python
在VS Code上搭建Python开发环境的方法
Apr 06 Python
Python装饰器用法实例总结
May 26 Python
python读取Excel实例详解
Aug 17 Python
python多线程并发实例及其优化
Jun 27 Python
python logging 日志的级别调整方式
Feb 21 Python
Python 爬取必应壁纸的实例讲解
Feb 24 Python
pytorch 计算ConvTranspose1d输出特征大小方式
Jun 23 Python
Python sklearn分类决策树方法详解
Sep 23 Python
python3 循环读取excel文件并写入json操作
Jul 14 #Python
Python爬虫实例——scrapy框架爬取拉勾网招聘信息
Jul 14 #Python
Python爬虫爬取新闻资讯案例详解
Jul 14 #Python
Win10下配置tensorflow-gpu的详细教程(无VS2015/2017)
Jul 14 #Python
Python实现图片查找轮廓、多边形拟合、最小外接矩形代码
Jul 14 #Python
python操作微信自动发消息的实现(微信聊天机器人)
Jul 14 #Python
python如何写try语句
Jul 14 #Python
You might like
PHP中调用JAVA
2006/10/09 PHP
用PHP产生动态的影像图
2006/10/09 PHP
特转载一高手总结PHP学习资源和链接.
2006/12/05 PHP
php 删除数组元素
2009/01/16 PHP
鸡肋的PHP单例模式应用详解
2013/06/03 PHP
php echo, print, print_r, sprintf, var_dump, var_expor的使用区别
2013/06/20 PHP
php去掉URL网址中带有PHPSESSID的配置方法
2014/07/08 PHP
js基于qrcode.js生成二维码的方法【附demo插件源码下载】
2016/12/28 PHP
php实现表单提交上传文件功能
2018/05/28 PHP
PHP的PDO连接讲解
2019/01/24 PHP
JavaScript中判断整字类型最简洁的实现方法
2014/11/08 Javascript
JavaScript中的console.group()函数详细介绍
2014/12/29 Javascript
javascript瀑布流式图片懒加载实例解析与优化
2016/02/23 Javascript
AngularJs  Creating Services详解及示例代码
2016/09/02 Javascript
js实现可旋转的立方体模型
2016/10/16 Javascript
vue.js 初体验之Chrome 插件开发实录
2017/05/13 Javascript
详解如何在Vue里建立长按指令
2018/08/20 Javascript
vue的过滤器filter实例详解
2018/09/17 Javascript
脚手架vue-cli工程webpack的作用和特点
2018/09/29 Javascript
vue 指令之气泡提示效果的实现代码
2018/10/18 Javascript
ES6 Iterator接口和for...of循环用法分析
2019/07/31 Javascript
js实现适配移动端的拖动效果
2020/01/13 Javascript
vue 实现图片懒加载功能
2020/12/31 Vue.js
用Python编写web API的教程
2015/04/30 Python
Python使用matplotlib的pie函数绘制饼状图功能示例
2018/01/08 Python
python3+PyQt5+Qt Designer实现堆叠窗口部件
2018/04/20 Python
Python切片索引用法示例
2018/05/15 Python
Django实现将views.py中的数据传递到前端html页面,并展示
2020/03/16 Python
python使用Windows的wmic命令监控文件运行状况,如有异常发送邮件报警
2021/01/30 Python
舞蹈毕业生的自我评价
2014/03/05 职场文书
交通事故调解协议书
2014/04/16 职场文书
敬老院献爱心活动总结
2014/07/08 职场文书
2015年幼儿教师个人工作总结
2015/05/20 职场文书
欠条格式范本
2015/07/03 职场文书
2015年社区国庆节活动总结
2015/07/30 职场文书
广播稿:校园广播稿范文
2019/04/17 职场文书