【问题标题】:Split CSV file into multiple (non-same-sized) files, keeping the headers将 CSV 文件拆分为多个(大小不同)文件,保留标题
【发布时间】:2019-06-18 02:17:22
【问题描述】:

我有一个较大的 csv (test.csv),其中包含以下标题列 id; type; name

以及以下值:

1; A; ASW23
2; C; SDF92
3; D; SDI22
4; D; ASD00
5; C; WPE03
6; D; PPO30
7; A; WER34
8; C; FHH88
9; C; FGE45
10; A; DFQ12
11; G; WWQ89
12; C; YDT63
13; D; QTT21

文件没有排序,我希望每次找到类型 A 时都拆分一个 CSV 文件,并保持相同的标题。例如:

test_1.csv

id; type; name
1; A; ASW23
2; C; SDF92
3; D; SDI22
4; D; ASD00
5; C; WPE03
6; D; PPO30

test_2.csv

id; type; name
7; A; WER34
8; C; FHH88
9; C; FGE45

test_3.csv

id; type; name
10; A; DFQ12
11; G; WWQ89
12; C; YDT63
13; D; QTT21

我正在努力为此编写 python 脚本,但我失败了。

【问题讨论】:

  • 到目前为止你尝试过什么?请发布您的代码。
  • 我正在考虑类似 stackoverflow.com/a/36446203/1971010 的事情,方法是使用一种“A”类型的计数器更改行限制 (1000)

标签: python csv


【解决方案1】:

你可以使用itertools.groupby:

import itertools, csv
data = list(csv.reader(open('test.csv'), delimiter=';'))[1:]
new_d = [[a, list(b)] for a, b in itertools.groupby(data, key=lambda x:x[1]==' A')]
new_groups = [new_d[i][-1]+new_d[i+1][-1] for i in range(0, len(new_d), 2)]
for i, a in enumerate(new_groups, 1):
  with open('test_{}.csv'.format(i), 'w') as f:
    write = csv.writer(f, delimiter=';')
    write.writerows([['id', 'type', 'name']]+a)

test_1.csv:

id;type;name
1; A; ASW23
2; C; SDF92
3; D; SDI22
4; D; ASD00
5; C; WPE03
6; D; PPO30

test_2.csv:

id;type;name
7; A; WER34
8; C; FHH88
9; C; FGE45

test_3.csv:

id;type;name
10; A; DFQ12
11; G; WWQ89
12; C; YDT63
13; D; QTT21

【讨论】:

  • @taleporos 没错。您只需要更改比较中字符串的值,即x[1]==' ASW23'。请注意字符串前面的空格;这是因为 csv read 函数中的分隔符本身被拆分,不包括它后面的空格。
  • @taleporos 啊,* 是仅在 Python3 中可用的解包语法。请参阅我最近的编辑,因为我添加了一个解决方案以使代码与 Python2/Python3 兼容。关于值更改,您确实只需要更改 key lambda 正文中的字符串。 range(0, 1, len(new_d)) 只迭代一次,步长值等于结构的长度。
  • @taleporos Opps,这是一个 f-string,它也与 Python 版本 format 的简单字符串格式。
  • @taleporos 好的。我在上面的解决方案中添加了[1:],以从原始测试文件中读取的data 中删除标题。
  • @taleporos 对,您只需要将字符串比较更改为x:x[7]==' X'。 new_groups = [new_d[i][-1]+new_d[i+1][-1] for i in range(0, len(new_d), 2)] 使用索引将new_d 的元素组合成两个一组,包含匹配字符串的列表即'A',以及不包含'A' 的所有后续条目?
【解决方案2】:

使用熊猫的方法。

>>> df = pd.read_csv('test.csv', sep=';')
>>> df.columns = [col.strip() for col in df.columns]
>>> df['cutter'] = pd.np.where(df['type'].str.strip() == 'A', 1, 0).cumsum()
>>> df
    id type    name  cutter
0    1    A   ASW23       1
1    2    C   SDF92       1
2    3    D   SDI22       1
3    4    D   ASD00       1
4    5    C   WPE03       1
5    6    D   PPO30       1
6    7    A   WER34       2
7    8    C   FHH88       2
8    9    C   FGE45       2
9   10    A   DFQ12       3
10  11    G   WWQ89       3
11  12    C   YDT63       3
12  13    D   QTT21       3

>>> gb = df.groupby('cutter')
>>> for i, x in enumerate(gb.groups):
...     gb.get_group(x).to_csv(f'test_{i}.csv', index=False)
... 

结果

test_1.csv

   id type    name  cutter
0   1    A   ASW23       1
1   2    C   SDF92       1
2   3    D   SDI22       1
3   4    D   ASD00       1
4   5    C   WPE03       1
5   6    D   PPO30       1

test_2.csv

   id type    name  cutter
0   7    A   WER34       2
1   8    C   FHH88       2
2   9    C   FGE45       2

test_3.csv

   id type    name  cutter
0  10    A   DFQ12       3
1  11    G   WWQ89       3
2  12    C   YDT63       3
3  13    D   QTT21       3

【讨论】:

    猜你喜欢
    • 2018-12-27
    • 2020-06-22
    • 1970-01-01
    • 2016-09-20
    • 2014-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多