将数据框拆分为单独的CSV文件

8
我有一个相当大的 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文件完成了这个操作:
步骤1
# -*- 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)

步骤2
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 文件时删除了标题行,但在这里我没有这样做吗?我不太确定在分割文件时需要执行什么操作以删除标题。
3个回答

12

为什么不直接按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进行改进。 参数 header=False 将不会写入标题,index_label=False 将不会写入索引列。

这将创建3个文件:

1.csv
2.csv
3.csv

每个 Column1 组都有相应的数据。


谢谢。回答你的问题,是因为今天我在谷歌上搜索解决方案时,一直看到pandas这个词。我没有意识到还有其他方法 :) - Steve Dallas
1
我尝试了这种方法,但它生成了一些奇怪的输出文件。以我的文件13.csv为例,它生成了一个带有标题的文件,并且似乎插入了一个没有标题的列,其中包含我不认识的数据。例如:+------+---------+---------+----------------+ | | Column1 | Column2 | NewColumn | | 6446 | 13 | 36457 | NewColumnValue | +------+---------+---------+----------------+ - Steve Dallas
1
你应该尝试使用g.to_csv('{}.csv'.format(i), header=False, index_label=False)header=False不会写入标题,index_label=False不会写入没有标题的列(这是数据框的索引)。 - Unatiel
1
太好了!我加了一个 'index=False',它就像魔法一样奏效了。感谢 cᴏʟᴅsᴘᴇᴇᴅ 和 @Unatiel。 - Steve Dallas

2

您不需要切换到 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)”之后,它运行得非常好。 - Steve Dallas

1

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')。 - Steve Dallas
我在使用Python3时没有遇到任何语法错误。话虽如此,@cᴏʟᴅsᴘᴇᴇᴅ的回答更好,你应该使用它。 - Unatiel
@SteveDallas 现在我想起来了,df = 确实会输出语法错误。我认为你在df = 之后不小心加了一个新行。我真的看不出我的代码中哪里有语法错误。不过我现在有点累了。 - Unatiel

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