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

11
我想将Excel表格读入Pandas DataFrame。然而,其中有合并的Excel单元格以及空行(完整/部分填充NaN),如下所示。为了澄清,John H.已经下订单购买从"The Bodyguard"到"Red Pill Blues"所有专辑。

Excel sheet capture

当我将这个Excel表格读入Pandas DataFrame时,Excel数据并没有被正确地传输。Pandas将合并的单元格视为一个单元格。DataFrame看起来像下面这样:(注意:括号中的值是我想要的期望值)

Dataframe capture

请注意,最后一行不包含合并单元格;它只有一个Artist列的值。
编辑: 我尝试使用以下方法向前填充NaN值:(Pandas:读取带有合并单元格的Excel)
df.index = pd.Series(df.index).fillna(method='ffill')  

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

3
你有尝试过什么吗?你能展示一下你的尝试吗?这篇帖子或许可以帮到你:https://dev59.com/tGAg5IYBdhLWcg3w_vOE - Vico
1
可能是Pandas:读取具有合并单元格的Excel文件的重复问题。 - John Y
1
@Vico - 不仅仅是有帮助,而且这是完全相同的问题! - John Y
@ Vico - 我已经尝试了链接中的解决方案,但它并不起作用。NaN值仍然存在。 - CPU
2个回答

11

您尝试访问的链接只需要填充索引列。对于您的使用情况,您需要对所有数据帧列执行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

0

使用条件语句:

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:标签[-1]不在[index]中。这个错误是由你代码的最后一行引起的。最后一行不应该是 df.loc[row[0], col] = df.loc[row[0]+1, col] 吗?如果你能在你的答案中包含内联注释来解释你的逻辑,那就太好了。我是Python Pandas的新手,希望能更好地理解你在这里的逻辑。谢谢。 - CPU
@ Manuel - 你的解决方案如何处理我Excel表格的最后一行(如上面的截图),其中它是一个普通行,具有未合并的单元格。看起来这一行与前一行(“Order_ID 15”)合并在一起,但是这最后一行是独立的。 - CPU
@ Manuel - 我重试了你的解决方案,但是我仍然遇到了相同的错误,因为我的DataFrame具有如下所示的索引标签:2,3,4,5,6,7,8,9,11,12,...。因此,没有行/索引标签10。我想重置索引标签,但出于项目目的,我不能这样做。如何迭代具有非连续索引标签的DataFrame(逐行)? - CPU
现在将每一行保存在'prow'中,前一行和'pprow'中保存前两行。现在,即使行号不连续,也不应该有任何问题。 - Manuel
@ Manuel - 你更新的代码对我来说部分有效。我尝试将你的解决方案实现到一个DataFrame字典中(df_dict = {sheet_name: Dataframe, sheet_name: Dataframe,...})。我得到了一些结果的组合:对于一些数据框,合并的单元格被正确地完全填充,而有些DF则只填充了部分内容,有些保留了合并的单元格。应该有一种方法可以在多个DataFrame的字典中完成这个任务... - CPU
如果所有的数据框格式都相同,那么它应该可以工作。单独测试不起作用的情况。 - Manuel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接