将不同长度的数字列从单独的文本文件合并到一个csv文件中



你好,我对Python编程相当陌生,似乎无法克服这个问题。

我有一个包含100个子文件夹的目录,每个子文件夹中有一个文本文件(没有文件扩展名),所有文件的名称完全相同。每个文件包含一列不同长度的数字。

我想将每个文件的所有数字合并到一个csv文件中,每个文件的数字在单独的列中。

所以我最终应该得到一个由100列组成的矩阵,这些列的数字长度不同,每列对应一个文件。

文件示例:

file1

1
15
23
22
10
文件2

3
55
22

我有这个脚本:

# import modules
import glob
import csv
import sys
import itertools
inf = glob.glob("*/*-ambig")
for f in inf:
    with open(f) as fin:
        with open(sys.argv[1], 'w') as fout:
            writer = csv.writer(fout, delimiter=',',  quotechar='', quoting=csv.QUOTE_NONE)
            headers = ('coverage', )
            writer.writerow(headers)
            for line in fin:
                columns = line.split("n") # split each column on new line
                writer.writerow(itertools.izip_longest(*columns, fillvalue=['']))

但是我得到这个错误:

Traceback (most recent call last):
  File "coverage_per_strain.py", line 21, in <module>
    writer.writerow(itertools.izip_longest(*columns, fillvalue=['']))
_csv.Error: sequence expected

有人知道我的代码有什么问题吗?你能看到其他错误吗?

谢谢!

csv.writerow需要一个序列作为参数。itertools.izip_longest返回一个迭代器。因此出现了错误信息。

你应该能够解决这个问题:

writer.writerow(list(itertools.izip_longest(*columns, fillvalue=[''])))

这是我在意识到您正在使用Python 2.7之前编写的解决方案。这只能在Python 3.3+中编写,因为它使用非常漂亮的contextlib.ExitStack上下文管理器,这只在该版本中添加(我还使用Python 3的map):

import glob
import csv
import sys
import contextlib
from itertools import zip_longest
in_filenames = glob.glob("*/*-ambig")
with contextlib.ExitStack() as stack:
    in_files = [stack.enter_context(open(filename)) for filename in in_filenames]
    out_file = stack.enter_context(open(sys.argv[1], "w", newlines=""))
    writer = csv.writer(out_file, delimiter=',', quoting=csv.QUOTE_NONE)
    writer.writerow(('coverage',)) # do you want the header repeated for each column?
    writer.writerows(zip_longest(*(map(str.strip, f) for f in in_files), fillvalue=""))

这是我尝试将它移植回Python 2。我没有测试过这个版本。我使用try/finally对来处理文件的关闭(和imap来处理剥离,而不预先将每个文件全部读入内存):

import glob
import csv
import sys
from itertools import izip_longest, imap
in_filenames = glob.glob("*/*-ambig")
with open(sys.argv[1], "wb") as out_file:
    in_files = []
    try:
        for filename in in_filenames:
            in_files.append(open(filename))
        writer = csv.writer(out_file, delimiter=',', quoting=csv.QUOTE_NONE)
        writer.writerow(('coverage',))
        writer.writerows(izip_longest(*[imap(str.strip, f) for f in in_files],
                                      fillvalue=""))
    finally:
        for f in in_files:
            try:
                f.close()
            except:   # ignore exceptions here, or the later files might not get closed!
                pass

最新更新