在 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中使用multiindex合并多个数据框

python 3 pandas和seaborn使用swarmplot进行斗争-multiIndex

Python 数据处理(二十九)—— MultiIndex 高级索引操作

如何在Python Pandas中将MultiIndex Dataframes与权重合并?

python 示例2:使用布尔表达式进行multiIndex切片

Python - reshape,pivot,unstack - multiindex