如何将带有 NaN 的合并 Excel 单元格读入 Pandas DataFrame

Posted

技术标签:

【中文标题】如何将带有 NaN 的合并 Excel 单元格读入 Pandas DataFrame【英文标题】:How to read merged Excel cells with NaN into Pandas DataFrame 【发布时间】:2018-05-29 18:18:55 【问题描述】:

我想将 Excel 工作表读入 Pandas DataFrame。但是,有合并的 Excel 单元格以及空行(完整/部分 NaN 填充),如下所示。澄清一下,John H. 已下订单购买从“保镖”到“红丸蓝调”的所有专辑。

当我将此 Excel 工作表读入 Pandas DataFrame 时,Excel 数据无法正确传输。 Pandas 将合并的单元格视为一个单元格。 DataFrame 如下所示:(注意:() 中的值是我想要的值)

请注意最后一行不包含合并单元格;它仅带有 Artist 列的值。


编辑: 我确实尝试了以下方法来向前填充 NaN 值:(Pandas: Reading Excel with merged cells)
df.index = pd.Series(df.index).fillna(method='ffill')  

但是,NaN 值仍然存在。 我可以使用什么策略或方法来正确填充 DataFrame? 是否有一种 Pandas 方法可以取消合并单元格并复制相应的内容?

【问题讨论】:

你有什么尝试吗?你能告诉我们你的尝试吗?希望这篇文章可以提供帮助:***.com/questions/22937650/… Pandas: Reading Excel with merged cells的可能重复 @Vico - 不仅有帮助,而且是完全相同的问题! @ Vico - 我已经尝试了链接中的解决方案,但是它不起作用。 NaN 值仍然存在。 【参考方案1】:

您尝试的引用链接只需要转发填充 index 列。对于您的用例,您需要为 all 数据框列 fillna。因此,只需向前填充整个数据框:

df = pd.read_excel("Input.xlsx")
print(df)

#    Order_ID Customer_name            Album_Name           Artist  Quantity
# 0       NaN           NaN            Radioshake              NaN       NaN
# 1       1.0       John H.         The Bodyguard  Whitney Houston       2.0
# 2       NaN           NaN              Lemonade          Beyonce       1.0
# 3       NaN           NaN  The Thrill Of It All        Sam Smith       2.0
# 4       NaN           NaN              Thriller  Michael Jackson      11.0
# 5       NaN           NaN                Divide       Ed Sheeran       4.0
# 6       NaN           NaN            Reputation     Taylor Swift       3.0
# 7       NaN           NaN        Red Pill Blues         Maroon 5       5.0

df = df.fillna(method='ffill')
print(df)

#    Order_ID Customer_name            Album_Name           Artist  Quantity
# 0       NaN           NaN            RadioShake              NaN       NaN
# 1       1.0       John H.         The Bodyguard  Whitney Houston       2.0
# 2       1.0       John H.              Lemonade          Beyonce       1.0
# 3       1.0       John H.  The Thrill Of It All        Sam Smith       2.0
# 4       1.0       John H.              Thriller  Michael Jackson      11.0
# 5       1.0       John H.                Divide       Ed Sheeran       4.0
# 6       1.0       John H.            Reputation     Taylor Swift       3.0
# 7       1.0       John H.        Red Pill Blues         Maroon 5       5.0

【讨论】:

【参考方案2】:

使用条件:

import pandas as pd

df_excel = pd.ExcelFile('Sales.xlsx')
df = df_excel.parse('Info')

for col in list(df):  # All columns
    pprow = 0
    prow = 1
    for row in df[1:].iterrows():  # All rows, except first
        if pd.isnull(df.loc[prow, 'Album Name']):  # If this cell is empty all in the same row too.
            continue
        elif pd.isnull(df.loc[prow, col]) and pd.isnull(df.loc[row[0], col]):  # If a cell and next one are empty, take previous valor. 
            df.loc[prow, col] = df.loc[pprow, col]
        pprow = prow
        prow = row[0]

输出(我用不同的名字):

    Order_ID Customer_name    Album Name
0        NaN           NaN         Radio
1        1.0          John            a 
2        1.0          John             b
3        1.0          John             c
4        1.0          John             d
5        1.0          John             e
6        1.0          John             f
7        NaN           NaN            GE
8        2.0         Harry   We are Born
9        3.0        Lizzy        Relapse
10       4.0           Abe         Smoke
11       4.0           Abe       Tell me
12       NaN           NaN           NaN
13       NaN           NaN      Best Buy
14       5.0        Kristy      The wall
15       6.0         Sammy  Kind of blue

【讨论】:

@Manuel - 我尝试了您的解决方案,但出现以下错误:KeyError: the label [-1] is not in the [index]。此错误是由代码的最后一行引起的。最后一行不应该是df.loc[row[0], col] = df.loc[row[0]+1, col]吗?如果您可以在答案中包含内联 cmets 来解释您的逻辑,那将不胜感激。我是 Python Pandas 的新手,想在这里更好地理解你的逻辑。谢谢。 @Manuel - 您的解决方案如何看待我的 Excel 工作表的最后一行(上面的屏幕截图),它是具有未合并单元格的普通行。看起来好像这一行与前一行 (Order_ID 15) 合并了,但最后一行是它自己的。 @Manuel - 我重试了你的解决方案,但我得到了同样的错误,因为我的 DataFrame 有这样的索引标签:2,3,4,5,6,7,8,9,11,12,...。因此,没有行/索引标签10。我想重置索引标签,但出于项目目的,我不能。如何迭代具有 非顺序 索引标签的 DataFrame(逐行)? 现在将每一行保存在“prow”、前一行和“pprow”前一行中。现在,即使行号不连续也应该没有问题。 @Manuel - 您更新的代码部分适用于我。我试图将您的解决方案实施到 DataFrames 字典 (df_dict = sheet_name: Dataframe, sheet_name: Dataframe,...) 中。我得到了结果的组合:对于某些数据框,合并的单元格完全正确填充,而一些 DF 部分填充,而一些保留合并的单元格。应该有办法在多个 DataFrames 的字典中做到这一点......

以上是关于如何将带有 NaN 的合并 Excel 单元格读入 Pandas DataFrame的主要内容,如果未能解决你的问题,请参考以下文章

Excel如何合并多个单元格内容到一个单元格?

如何通过Java 合并和取消合并 Excel 单元格

记录解析具有合并单元格的Excel

excel合并单元格怎么弄

如何将多个excel表格内容合到一起

phpexcel 合并单元格后插入图片 如何让图片居中