当前位置: 首页 > 科技观察

修复了Pandas包的一个bug

时间:2023-03-13 19:56:12 科技观察

大家好,我是zhenguo,今天说点开心的事~1.修复这个bug导出有层级关系的列头时,会多写一个空行,这个错误不断发生。2、定位问题经过调试,发现bug发生的位置锁定在excel.py模块中,如下图:原因excel.py模块封装的方法。经过调试,发现write方法中的以下几行代码是关键逻辑:写入excel的过程其实就是一条一条写入excel的过程,主要是调用封装的get_formatted_cells方法获取formatted_cells。formatted_cells=self.get_formatted_cells()writer.write_cells(formatted_cells,sheet_name,startrow=startrow,startcol=startcol,freeze_panes=freeze_panes,)进去看看get_formatted_cells方法,用chain连接两个generator,然后yield它们一个一个地输出:defget_formatted_cells(self):forcellinitertools.chain(self._format_header(),self._format_body()):cell.val=self._format_value(cell.val)yieldcell并连接这些两次迭代,一次是self._format_header(),一次是self._format_body()。经过调试,bug的原因可以在这里找到,self._format_body()有问题,在格式化数据字段部分之后。以文章开头的案例为例。值为a的单元格对应的行索引被错误标记为3,注意行索引是从0开始的,显然,实际应该是2。3.修复BUG并找到原因后,下钻到底层方法,调试后找到self._format_body()中调用的_format_regular_rows方法。与行号关联的属性是self.rowcounter,所以重点关注其相关的写法逻辑:def_format_regular_rows(self):has_aliases=isinstance(self.header,(tuple,list,np.ndarray,Index))ifhas_aliasesorself.header:self.rowcounter+=1#输出索引和索引标签?ifself.index:#检查别名#iflistonlytakefirst因为这不是MultiIndexifself.index_labelandisinstance(self.index_label,(list,tuple,np.ndarray,Index)):index_label=self.index_label[0]#ifstringgoodtogoelifself.index_labelandisinstance(self.index_label,str):index_label=self.index_labelelse:index_label=self.df.index.names[0]ifisinstance(self.columns,ABCMultiIndex):self.rowcounter+=1一共有2种可能的写法,第二种写法,也就是上面代码块的最后两行,是bug的原因。仔细分析,在级联表头(ABCMultiIndex)写入excel的场景中,行索引已经在self._format_header()中,行索引已经加1,所以这里重复加1:ifisinstance(self.columns,ABCMultiIndex):self.rowcounter+=1,所以修改方法就是标记一下。4、bug修复后,经过测试,级联列头和单个列头都正常,没有多余的空行。以上,我已经把这个bug提交到github上的pandas,希望能帮助到更多的开发者。我是zhenguo,希望点赞+转发~