【问题标题】:Pandas: How to read a DataFrame from excel-file where multiple rows are sometimes separated by line break (\n)Pandas:如何从 excel 文件中读取 DataFrame,其中多行有时由换行符 (\n) 分隔
【发布时间】:2019-09-01 04:11:17
【问题描述】:

我正在尝试读取 pandas 中的一些 excel 文件。在某些文件中,感兴趣的表格式不完美,即多行被格式化为单行,但每一行都有多行。因此,当您查看 excel 文件时,数据看起来很好。此外,当使用 pandas 解析它时,每一行的末尾确实有一个换行符 (\n)。

问题是,当我使用 read_excel() 函数读取它时,它会将其转换为 DataFrame,该 DataFrame 不会将此换行符视为单独的行,而是将其放入其中包含 \n 的一行。我想编写一个代码,将 N 行的每一行视为/转换为 N 行(使用换行符作为新行的指示符)。

在解析文件或在 Python 中对数据帧进行后处理时,有没有办法做到这一点?

在这里,我提供了一个非常简化的虚拟 excel 文件和一些代码来解释问题。

Excel 文件示例:

Name                | Price
-------------------------------
Coca Cola           |     46.66
-------------------------------
Google              |   1204.44
Facebook            |    177.58
-------------------------------
Berkshire Hathaway  | 306513.75

我只是在 Python 中使用 Pandas 的 read_excel:

dataframe_parsed = pandas.read_excel(file_name)
print(dataframe_parsed.head())

我得到以下 DataFrame 作为输出:

                 Name            Price
0           Coca Cola            46.66
1    Google\nFacebook  1204.44\n177.58
2  Berkshire Hathaway        306513.75

想要的输出是:

                 Name           Price
0           Coca Cola           46.66
1              Google         1204.44
2            Facebook          177.58
3  Berkshire Hathaway       306513.75

我们将不胜感激任何帮助。

【问题讨论】:

    标签: python excel pandas dataframe parsing


    【解决方案1】:

    split 之后,您可以通过unnesting 查询

    yourdf=unnesting(df.apply(lambda x : x.str.split(r'\\n')),['Name','Price'])
    yourdf
    Out[50]: 
                     Name      Price
    0           Coca Cola      46.66
    1              Google    1204.44
    1            Facebook     177.58
    2  Berkshire Hathaway  306513.75
    

    def unnesting(df, explode):
        idx = df.index.repeat(df[explode[0]].str.len())
        df1 = pd.concat([
            pd.DataFrame({x: np.concatenate(df[x].values)}) for x in explode], axis=1)
        df1.index = idx
    
        return df1.join(df.drop(explode, 1), how='left')
    

    由于你上面提到的不起作用

    df.apply(lambda x : x.str.split(r'\\n')).stack().apply(pd.Series).stack().unstack(level=1).reset_index(drop=True)
    Out[57]: 
                     Name      Price
    0           Coca Cola      46.66
    1              Google    1204.44
    2            Facebook     177.58
    3  Berkshire Hathaway  306513.75
    

    【讨论】:

    • @FridaSchenker 你有空行,这会导致错误,如果你确定你的数据格式和你展示给我们的一样,我的代码会工作
    • 感谢您的帮助。但很抱歉,它不起作用。我再次检查,我的数据框中没有空行。您的第二段代码只是将第二列转换为 NaN。所以还是没有解决办法。
    • @FridaSchenker 对不起,我不能使用那个链接。当你尝试我的解决方案时,也许你可以拿出一个更好的示例数据可以重现错误代码
    【解决方案2】:

    感谢文本的帮助。但我无法让您的代码产生所需的输出。但是,使用您的unnesting 链接,我想出了一个解决方案,并从该页面上的@user3483203 的答案中得到了一些帮助。我在这里发布解决方案,以防万一它可以帮助面临类似问题的人:

    import pandas as pd
    import numpy as np
    
    def main():
        # Make a simple dummy dataframe for testing
        my_dataframe = pd.DataFrame({'ColA':["a1", "a2\na3", "a4\n a5 space"],'ColB':["b1", "b2\nb3","b4\nb5"]})
        print("DataFrame before:\n", my_dataframe.head())
    
        my_dataframe_after = myUnnesting(my_dataframe)
        print("DataFrame after:\n", my_dataframe_after.head())
    
    def myUnnesting(dataframe):
        new_dataframe = pd.DataFrame()
        for column in dataframe:
            # Convert each column into an array of lists and concatenate these lists into a single array 
            col_vals = np.concatenate(np.array(dataframe[column].str.split("\n")))
            new_dataframe[column] = col_vals 
    
        return new_dataframe
    
    if __name__ == "__main__":
        main()
    

    输出:

    DataFrame before:
                 ColA    ColB
    0             a1      b1
    1         a2\na3  b2\nb3
    2  a4\n a5 space  b4\nb5
    DataFrame after:
             ColA ColB
    0         a1   b1
    1         a2   b2
    2         a3   b3
    3         a4   b4
    4   a5 space   b5
    

    当然,此解决方案假定对于给定的行,每列中有相同数量的 \n。这个假设对我正在处理的数据非常有效。但是,如果有人阅读本文想发布一个更通用的解决方案,该解决方案也适用于其他情况,我们将不胜感激。谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-21
      • 1970-01-01
      • 1970-01-01
      • 2023-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多