【问题标题】:Splitting a dataframe into separate CSV files将数据框拆分为单独的 CSV 文件
【发布时间】:2018-02-17 20:46:13
【问题描述】:

我有一个相当大的 csv,如下所示:

+---------+---------+
| Column1 | Column2 |
+---------+---------+
|       1 |   93644 |
|       2 |   63246 |
|       3 |   47790 |
|       3 |   39644 |
|       3 |   32585 |
|       1 |   19593 |
|       1 |   12707 |
|       2 |   53480 |
+---------+---------+

我的目的是

  1. 添加新列
  2. 在 csv 每一行的该列“NewColumnValue”中插入一个特定值
  3. 根据 Column1 中的值对文件进行排序
  4. 根据 'Column1' 的内容将原始 CSV 拆分为新文件,删除标题

例如,我希望得到多个文件,如下所示:

+---+-------+----------------+
| 1 | 19593 | NewColumnValue |
| 1 | 93644 | NewColumnValue |
| 1 | 12707 | NewColumnValue |
+---+-------+----------------+

+---+-------+-----------------+
| 2 | 63246 | NewColumnValue |
| 2 | 53480 | NewColumnValue |
+---+-------+-----------------+

+---+-------+-----------------+
| 3 | 47790 | NewColumnValue |
| 3 | 39644 | NewColumnValue |
| 3 | 32585 | NewColumnValue |
+---+-------+-----------------+

我已经设法使用单独的 .py 文件来做到这一点:

第一步

# -*- coding: utf-8 -*-
import pandas as pd
df = pd.read_csv('source.csv')
df = df.sort_values('Column1')
df['NewColumn'] = 'NewColumnValue'
df.to_csv('ready.csv', index=False, header=False)

第二步

import csv
from itertools import groupby
for key, rows in groupby(csv.reader(open("ready.csv")),
                         lambda row: row[0]):
    with open("%s.csv" % key, "w") as output:
        for row in rows:
            output.write(",".join(row) + "\n")

但我真的很想学习如何在一个 .py 文件中完成所有工作。我试过这个:

# -*- coding: utf-8 -*-
#This processes a large CSV file.  
#It will dd a new column, populate the new column with a uniform piece of data for each row, sort the CSV, and remove headers
#Then it will split the single large CSV into multiple CSVs based on the value in column 0 
import pandas as pd
import csv
from itertools import groupby
df = pd.read_csv('source.csv')
df = df.sort_values('Column1')
df['NewColumn'] = 'NewColumnValue'
for key, rows in groupby(csv.reader((df)),
                         lambda row: row[0]):
    with open("%s.csv" % key, "w") as output:
        for row in rows:
            output.write(",".join(row) + "\n")

但它没有按预期工作,而是为我提供了多个以每个列标题命名的 CSV。

发生这种情况是因为我在使用单独的 .py 文件时删除了标题行,而我没有在这里做吗?我不确定在拆分文件以删除标题时需要执行什么操作。

【问题讨论】:

    标签: python pandas dataframe group-by pandas-groupby


    【解决方案1】:

    您无需切换到itertools 进行过滤,pandas 已内置所有必要的功能。

    # -*- coding: utf-8 -*-
    import pandas as pd
    df = pd.read_csv('source.csv')
    df = df.sort_values('Column1')  # Sorting isn't needed
    df['NewColumn'] = 'NewColumnValue'
    for key in df['Column1'].unique():  # For each value in Column1
        # These two steps can be combined into a single call
        # I'll separate for clarity:  
        # 1) filter the dataframe on the unique value
        dw = df[df['Column1']==key]   
        # 2) write the resulting dataframe without headers
        dw.to_csv("%s.csv" % key, header=False)  
    

    【讨论】:

    • 感谢您的回答。它在第 12 行给了我一个错误,但是在我将其更改为 "dw.to_csv("%s.csv" % key, header=False) " 之后效果很好。
    【解决方案2】:

    pandas.DataFrame 支持将其数据写入 csv to_csv() 的方法。在这种情况下,您不需要 csv 模块。

    import pandas as pd
    
    df = pd.read_csv('source.csv')
    df = df.sort_values('Column1').set_index('Column1')
    df['NewColumn'] = 'NewColumnValue'
    for key in df.index.unique():
        df.loc[key].to_csv('%d.csv' % int(key), header=False)
    

    for key df.index.unique(): 将遍历索引中的每个唯一值。在您的示例中,它将遍历(1, 2 , 3)header=False 将确保不将标头写入输出文件。

    要解释为什么您在示例中得到错误输出,请尝试print(list(df))。这应该输出 df 中的所有列。这就是for key, rows in csv.reader((df)): 迭代 df 中的列的原因。

    实际上,您应该为数据框中的每一列获取 1 个 csv,它们的内容可能类似于 ,[NAME_OF_COLUMN],<itertools.... object at 0x.....>

    【讨论】:

    • 感谢您的回答。但是,我收到语法错误:df = df.sort_values('Column1').set_index('Column1')
    • 我没有得到任何语法错误,使用 python3。话虽如此,@cᴏʟᴅsᴘᴇᴇᴅ 的答案更好,你应该改用它。
    • @SteveDallas 现在想想,df = 确实会输出语法错误。我认为您在df = 之后错误地添加了新行。我真的看不出我的代码中的语法错误在哪里。不过我现在有点累了。
    【解决方案3】:

    为什么不只是 groupby Column1 并保存每个组?

    df = df.sort_values('Column1').assign(NewColumn='NewColumnValue')
    print(df)
    
       Column1  Column2       NewColumn
    0        1    93644  NewColumnValue
    5        1    19593  NewColumnValue
    6        1    12707  NewColumnValue
    1        2    63246  NewColumnValue
    7        2    53480  NewColumnValue
    2        3    47790  NewColumnValue
    3        3    39644  NewColumnValue
    4        3    32585  NewColumnValue
    

    for i, g in df.groupby('Column1'):
        g.to_csv('{}.csv'.format(i), header=False, index_label=False)
    

    感谢 Unatiel 提供improvementheader=False 不会写标题,index_label=False 不会写索引列。

    这会创建 3 个文件:

    1.csv
    2.csv
    3.csv
    

    每个都有对应于每个Column1组的数据。

    【讨论】:

    • 谢谢。为了回答你的问题,这是因为当我今天花时间在谷歌上搜索解决问题的方法时,熊猫不断出现。我没有意识到还有另一种方法:)
    • @SteveDallas Np。如果你决定使用它,你可以accept this answer
    • 我试过这个方法,它产生了一些奇怪的输出文件。以我的文件 13.csv 为例,它会生成一个带有标题的文件,此外它似乎正在插入一个带有我不认识的数据的无标题列。例如+--------+---------+---------+----------------+ | |第 1 列 |第 2 列 |新专栏 | | 6446 | 13 | 36457 |新列值 | +------+---------+---------+----------------+
    • 你应该试试g.to_csv('{}.csv'.format(i), header=False, index_label=False)header=False 不会写入标题,index_label=False 不会写入无标题列(这是您的数据帧的索引)。
    • 太棒了!我添加了一个'index = False',它就像一个魅力。感谢 cᴏʟᴅsᴘᴇᴇᴅ 和 @Unatiel
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-17
    • 2020-01-12
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多