python之DataFrame实现excel合并单元格


Posted in Python onFebruary 22, 2021

在工作中经常遇到需要将数据输出到excel,且需要对其中一些单元格进行合并,比如如下表表格,需要根据A列的值,合并B、C列的对应单元格

python之DataFrame实现excel合并单元格

pandas中的to_excel方法只能对索引进行合并,而xlsxwriter中,虽然提供有merge_range方法,但是这只是一个和基础的方法,每次都需要编写繁琐的测试才能最终调好,而且不能很好的重用。所以想自己写一个方法,结合dataframe和merge_range。大概思路是:

1、定义一个MY_DataFrame类,继承DataFrame类,这样能很好的利用pandas的很多特性,而不用自己重新组织数据结构。
2、定义一个my_mergewr_excel方法,参数分别为:输出excel的路径、用于判断是否需要合并的key_cols列表、用于指明哪些列上的单元格需要被合并的列表
3、将MY_DataFrame封装为一个My_Module模块,以备重用。

合并的算法如下:

1、根据给定参数的【关键列】,进行分组计数和排序,添加CN和RN两个辅助列
2、判断CN大于1的,该分组需要合并,否则该分组(行)无需合并(CN=1说明这个分组数据行是唯一的,无需合并)
3、对应需要合并的分组,判断当前列是不是在给定参数【合并列】中,是则用合并写excel单元格,否则就是普通的写excel单元格。
4、在需要合并的列中,如果对于的RN=1则调用merge_range,一次性写想下写CN个单元格,如果RN>1则跳过该单元格,因为在RN=1的时候,已经合并写了该单元格,若再重复调用erge_range,打开excel文档时会报错。

用图解释如下:

python之DataFrame实现excel合并单元格

具体代码如下:

# -*- coding: utf-8 -*- 
""" 
Created on 20170301 
 
@author: ARK-Z 
""" 
import xlsxwriter 
 
 
import pandas as pd 
 
class My_DataFrame(pd.DataFrame): 
 def __init__(self, data=None, index=None, columns=None, dtype=None, copy=False): 
  pd.DataFrame.__init__(self, data, index, columns, dtype, copy) 
 
 def my_mergewr_excel(self,path,key_cols=[],merge_cols=[]): 
  # sheet_name='Sheet1', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, startrow=0, startcol=0, engine=None, merge_cells=True, encoding=None, inf_rep='inf', verbose=True): 
  self_copy=My_DataFrame(self,copy=True) 
  line_cn=self_copy.index.size 
  cols=list(self_copy.columns.values) 
  if all([v in cols for i,v in enumerate(key_cols)])==False:  #校验key_cols中各元素 是否都包含与对象的列 
   print("key_cols is not completely include object's columns") 
   return False 
  if all([v in cols for i,v in enumerate(merge_cols)])==False: #校验merge_cols中各元素 是否都包含与对象的列 
   print("merge_cols is not completely include object's columns") 
   return False  
 
  wb2007 = xlsxwriter.Workbook(path) 
  worksheet2007 = wb2007.add_worksheet() 
  format_top = wb2007.add_format({'border':1,'bold':True,'text_wrap':True}) 
  format_other = wb2007.add_format({'border':1,'valign':'vcenter'}) 
  for i,value in enumerate(cols): #写表头 
   #print(value) 
   worksheet2007.write(0,i,value,format_top) 
   
  #merge_cols=['B','A','C'] 
  #key_cols=['A','B'] 
  if key_cols ==[]: #如果key_cols 参数不传值,则无需合并 
   self_copy['RN']=1 
   self_copy['CN']=1 
  else: 
   self_copy['RN']=self_copy.groupby(key_cols,as_index=False).rank(method='first').ix[:,0] #以key_cols作为是否合并的依据 
   self_copy['CN']=self_copy.groupby(key_cols,as_index=False).rank(method='max').ix[:,0] 
  #print(self) 
  for i in range(line_cn): 
   if self_copy.ix[i,'CN']>1: 
    #print('该行有需要合并的单元格') 
    for j,col in enumerate(cols): 
     #print(self_copy.ix[i,col]) 
     if col in (merge_cols): #哪些列需要合并 
      if self_copy.ix[i,'RN']==1: #合并写第一个单元格,下一个第一个将不再写 
       worksheet2007.merge_range(i+1,j,i+int(self_copy.ix[i,'CN']),j, self_copy.ix[i,col],format_other) ##合并单元格,根据LINE_SET[7]判断需要合并几个 
       #worksheet2007.write(i+1,j,df.ix[i,col]) 
      else: 
       pass 
      #worksheet2007.write(i+1,j,df.ix[i,j]) 
     else: 
      worksheet2007.write(i+1,j,self_copy.ix[i,col],format_other) 
     #print(',') 
   else: 
    #print('该行无需要合并的单元格') 
    for j,col in enumerate(cols): 
     #print(df.ix[i,col]) 
     worksheet2007.write(i+1,j,self_copy.ix[i,col],format_other) 
     
     
  wb2007.close() 
  self_copy.drop('CN', axis=1) 
  self_copy.drop('RN', axis=1)

调用代码:

import My_Module 
 
DF=My_DataFrame({'A':[1,2,2,2,3,3],'B':[1,1,1,1,1,1],'C':[1,1,1,1,1,1],'D':[1,1,1,1,1,1]}) 
 
DF 
Out[120]: 
 A B C D 
0 1 1 1 1 
1 2 1 1 1 
2 2 1 1 1 
3 2 1 1 1 
4 3 1 1 1 
5 3 1 1 1 

DF.my_mergewr_excel('000_2.xlsx',['A'],['B','C'])

效果如下:

python之DataFrame实现excel合并单元格

也可以设置合并A、B列:

DF.my_mergewr_excel('000_2.xlsx',['A'],['A','B'])

效果如下:

python之DataFrame实现excel合并单元格

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python循环监控远程端口的方法
Mar 14 Python
python结合selenium获取XX省交通违章数据的实现思路及代码
Jun 26 Python
Python实现利用最大公约数求三个正整数的最小公倍数示例
Sep 30 Python
python3 破解 geetest(极验)的滑块验证码功能
Feb 24 Python
python使用magic模块进行文件类型识别方法
Dec 08 Python
详解Python:面向对象编程
Apr 10 Python
Python使用numpy模块实现矩阵和列表的连接操作方法
Jun 26 Python
Python 正则表达式 re.match/re.search/re.sub的使用解析
Jul 22 Python
基于python解线性矩阵方程(numpy中的matrix类)
Oct 21 Python
Python装饰器如何实现修复过程解析
Sep 05 Python
Python可变与不可变数据和深拷贝与浅拷贝
Apr 06 Python
Python使用BeautifulSoup4修改网页内容
May 20 Python
python合并同类型excel表格的方法
Apr 01 #Python
python实现两个文件合并功能
Apr 01 #Python
Python中一行和多行import模块问题
Apr 01 #Python
Python对List中的元素排序的方法
Apr 01 #Python
Python去除、替换字符串空格的处理方法
Apr 01 #Python
利用scrapy将爬到的数据保存到mysql(防止重复)
Mar 31 #Python
python 通过xml获取测试节点和属性的实例
Mar 31 #Python
You might like
十天学会php之第八天
2006/10/09 PHP
PHP中实现接收多个name相同但Value不相同表单数据实例
2015/02/03 PHP
php递归遍历多维数组的方法
2015/04/18 PHP
yii2.0整合阿里云oss上传单个文件的示例
2017/09/19 PHP
YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用示例
2020/03/18 PHP
Jquery实战_读书笔记1—选择jQuery
2010/01/22 Javascript
javascript温习的一些笔记 基础常用知识小结
2011/06/22 Javascript
编写高效jQuery代码的4个原则和5个技巧
2014/04/24 Javascript
javascript 判断整数方法分享
2014/12/16 Javascript
Backbone.js框架中Model与Collection的使用实例
2016/05/07 Javascript
利用BootStrap的Carousel.js实现轮播图动画效果
2016/12/21 Javascript
详解vue 中使用 AJAX获取数据的方法
2017/01/18 Javascript
react-router JS 控制路由跳转实例
2017/06/15 Javascript
详解vue2父组件传递props异步数据到子组件的问题
2017/06/29 Javascript
深入理解ES7的async/await的用法
2017/09/09 Javascript
webpack4 处理SCSS的方法示例
2018/09/03 Javascript
vue 的点击事件获取当前点击的元素方法
2018/09/15 Javascript
解决vue2中使用elementUi打包报错的问题
2020/09/22 Javascript
Node.js利用Express实现用户注册登陆功能(推荐)
2020/10/26 Javascript
antd table按表格里的日期去排序操作
2020/11/17 Javascript
python编写网页爬虫脚本并实现APScheduler调度
2014/07/28 Python
python3.6连接MySQL和表的创建与删除实例代码
2017/12/28 Python
Python 经典面试题 21 道【不可错过】
2018/09/21 Python
python控制nao机器人身体动作实例详解
2019/04/29 Python
flask 使用 flask_apscheduler 做定时循环任务的实现
2019/12/10 Python
为什么黑客都用python(123个黑客必备的Python工具)
2020/01/31 Python
如何在sublime编辑器中安装python
2020/05/20 Python
使用python将微信image下.dat文件解密为.png的方法
2020/11/30 Python
canvas实现烟花的示例代码
2020/01/16 HTML / CSS
美国知名珠宝首饰品牌:Gemvara
2017/10/06 全球购物
Hello Molly美国:女性时尚在线
2019/08/26 全球购物
农村党支部书记司法四风问题对照检查材料
2014/09/26 职场文书
社区义诊通知
2015/04/24 职场文书
乡镇法制宣传日活动总结
2015/05/05 职场文书
2015年度工程师评职称工作总结
2015/10/14 职场文书
解决redis sentinel 频繁主备切换的问题
2021/04/12 Redis