在 Python 中使用 MultiIndex 和 to_excel 时创建的标题下方的空行
Posted
技术标签:
【中文标题】在 Python 中使用 MultiIndex 和 to_excel 时创建的标题下方的空行【英文标题】:Blank line below headers created when using MultiIndex and to_excel in Python 【发布时间】:2019-03-01 00:58:53 【问题描述】:我正在尝试使用带有 XlsxWriter 的 to_excel 函数将 Pandas 数据框保存到 excel 文件中。
当我将数据框打印到终端时,它会按原样读取,但是当我将其保存到 excel 并打开文件时,标题下方有一个额外的空白行,它不应该存在。这只发生在使用 MultiIndex 作为标头时,但我需要它提供的分层标头,但我找不到解决方案。
以下是来自在线 MultiIndex 示例的代码,它产生的结果与我正在处理的项目相同。任何解决方案将不胜感激。
import numpy as np
import pandas as pd
import xlsxwriter
tuples = [('bar', 'one'), ('bar', 'two'), ('baz', 'one'), ('baz', 'two'), ('foo', 'one'), ('foo', 'two'), ('qux', 'one'), ('qux', 'two')]
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
iterables = [['bar', 'baz', 'foo', 'qux'], ['one', 'two']]
pd.MultiIndex.from_product(iterables, names=['first', 'second'])
df = pd.DataFrame(np.random.randn(3, 8), index=['A', 'B', 'C'], columns=index)
print(df)
writer = pd.ExcelWriter('test.xlsx', engine='xlsxwriter')
df.to_excel(writer, sheet_name='test1')
创建的 excel 输出:
【问题讨论】:
【参考方案1】:这很可能是 pandas 中的一个错误。
有关建议的解决方案,请参阅this question:
没有简单的方法可以通过读取 xlsx 来删除该行 再次。
还有一个指向GitHub issue 的链接,用于解决该主题。
所以我做了这个解决方法,它可能对你有帮助:
df = pd.read_excel('/home/teoretic/test.xlsx', index_col=0)
df = df.drop(np.nan) # <== dropping an empty row
rename_dct = dict.fromkeys(df.loc[:,df.columns.str.contains('^Unnamed')], '')
df = df.rename(columns=rename_dct) # <== renaming 'Unnamed' columns to blank space
writer = pd.ExcelWriter('/home/teoretic/test_new.xlsx', engine='xlsxwriter')
df.to_excel(writer, sheet_name='test1')
writer.close()
这是一个输出文件:
【讨论】:
非常感谢您的回复,我希望有办法让第一行单元格保持合并但不用担心。 我试图保留多索引,但是当我将它保存到xlsx
时,最终会遇到相同的“空白行”问题。找不到出路,但这不是完美的解决方法:)
我已经设法找到一种解决方法,将标题的第一行单独写入 excel,然后通过“workbook.merge_range()”合并相关单元格,然后将其余数据合并通过在 'to_excel' 中指定 'startrow=1' 在下面添加。
@JamesSalmon 你能把你的工作作为这个问题的解决方案吗?
@JamesSalmon 您可以将您的解决方法发布为对我的答案的编辑,以防止出现多个答案【参考方案2】:
非常感谢这个问题和@Teoretic 的解决方法。
但是,在我的情况下,Multiindex
列的合并单元格非常有用,而 @Teoretic 的列则丢失了这些单元格。我已经完成了另一种解决方法,在编写之前隐藏了整行,它可以工作,因此我将它包含在此处以防对任何人有用。
writer = pd.ExcelWriter('test.xlsx', engine='xlsxwriter')
df.to_excel(writer, sheet_name='test1')
writer.sheets['test1'].set_row(2, None, None, 'hidden': True)
writer.save()
【讨论】:
【参考方案3】:我找到了使用 openpyxl 包的以下解决方法,方法是读取带有空行的文件,删除该行并重新写入文件。我发现这种方法的优点是它保留了 MultiIndex 列中漂亮的合并单元格,实际上从 Excel 文件中删除了空行。通过实际删除空行,如果您的其余数据是数字,这将允许您在电子表格中开箱即用地使用 Excel 的过滤功能,而无需手动删除文件中的空行。
# Assuming df is your data frame with MultiIndex columns that you have already written to Excel
# Load the file with the empty line and select the sheet you want to edit
wb = openpyxl.load_workbook(filename = 'file_with_empty_line.xlsx')
ws = wb['sheet_name_to_edit']
# The row number to delete is 1-indexed in Excel
row_to_delete = df.columns.nlevels
ws.delete_rows(row_to_delete)
# If you want to write the name of the index into the empty cell above the index col
# after deleting the row (assuming you are writing to the first column):
ws['A'+str(row_to_delete)]=df.index.name
# Save the modified workbook to file
wb.save(filename = 'file_without_emtpy_line.xlsx')
虽然必须导入整个包来处理此问题并不理想,但我的用例要求我不要简单地隐藏缺失的行。 @lrnzcig 的解决方案会更好,如果您只需隐藏空行即可。
【讨论】:
【参考方案4】:我使用 ExcelWriter 删除了那个空白行。我正在将 df 添加到现有工作表中。
with pd.ExcelWriter(“PATH_TO_EXCEL”,mode=“a”,engine=“openpyxl”) as writer:
writer.book=load_workbook(“PATH_TO_EXCEL”)
df.to_excel(writer,sheet_name=“sample”,startrow=0,startcol=0)
writer.sheets[‘sample’].delete_rows(3)
【讨论】:
以上是关于在 Python 中使用 MultiIndex 和 to_excel 时创建的标题下方的空行的主要内容,如果未能解决你的问题,请参考以下文章
python 3 pandas和seaborn使用swarmplot进行斗争-multiIndex
Python 数据处理(二十九)—— MultiIndex 高级索引操作
如何在Python Pandas中将MultiIndex Dataframes与权重合并?