视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
python之DataFrame实现excel合并单元格_python
2020-11-27 14:13:12 责编:小OO
文档
这篇文章主要为大家详细介绍了python之DataFrame实现excel合并单元格,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

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文档时会报错。

用图解释如下:

具体代码如下:

# -*- 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'])

效果如下:

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

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

效果如下:

下载本文
显示全文
专题