将defaultdict(list)写入文件

3

之前有一个问题使用defaultdict解析多分隔符文件

虽然代码可以得到所需的输出,但我无法将其以表格形式写入文件中。

         count pos _pos _neg
31022550     
31022550    
31022550    
31022550

ids:

for key, rows in ids.iteritems():
     for row in rows:
         print '{}\t{}'.format(key, row)

31022550    {'count': '0', 'base': '=', 'pos': '20', '_neg': '0', '_pos': '0'}
31022550    {'count': '2', 'base': 'A', 'pos': '20', '_neg': '0', '_pos': '2'}
31022550    {'count': '0', 'base': 'C', 'pos': '20', '_neg': '0', '_pos': '0'}
31022550    {'count': '1391', 'base': 'G', 'pos': '20', '_neg': '672', '_pos': '719'}
31022550    {'count': '1', 'base': 'T', 'pos': '20', '_neg': '1', '_pos': '0'}
31022440    {'count': '0', 'base': 'N', 'pos': '20', '_neg': '0', '_pos': '0'}
31022550    {'count': '2', 'base': '+A', 'pos': '20', '_neg': '0', '_pos': '2'}
31022551    {'count': '0', 'base': '=', 'pos': '20', '_neg': '0', '_pos': '0'}
31022551    {'count': '960', 'base': 'A', 'pos': '20', '_neg': '464', '_pos': '496'}
31022551    {'count': '0', 'base': 'C', 'pos': '20', '_neg': '0', '_pos': '0'}
31022551    {'count': '13', 'base': 'G', 'pos': '20', '_neg': '9', '_pos': '4'}
31022551    {'count': '0', 'base': 'T', 'pos': '20', '_neg': '0', '_pos': '0'}
31022551    {'count': '0', 'base': 'N', 'pos': '20', '_neg': '0', '_pos': '0'}
31022551    {'count': '288', 'base': '+G', 'pos': '20', '_neg': '117', '_pos': '171'}
31022551    {'count': '9', 'base': '+GG', 'pos': '20', '_neg': '4', '_pos': '5'}
31022551    {'count': '1', 'base': '+GGG', 'pos': '20', '_neg': '0', '_pos': '1'}

代码

with open('mycsvfile.csv', 'w') as f:
    writer = csv.writer(f)
    for k, v in ids.iteritems():
        writer.writerow([k] + v)

1
你能提供你问题中 ids 的内容吗? - Jean-François Fabre
@Jean-FrançoisFabre 更新了帖子。 - novicebioinforesearcher
最简单的方法是将 print '{}\t{}'.format(key, row) 替换为 writer.writerow([key, row['count'], row['pos'], row['_pos'], row['_neg']]) - Steven Rumbalski
1个回答

3
我会这样做(Python 2):
with open('mycsvfile.csv', 'wb') as f:  # binary is better, avoids blank lines in some python 2 versions
    writer = csv.writer(f,delimiter="\t")
    keys=["count","pos","_pos","_neg"]
    writer.writerow([""]+keys)
    for k, vl in ids.iteritems():
        for v in vl:
            writer.writerow([k] + [v[key] for key in keys])

您需要使用双重循环来遍历每个键的列表。我已将列名称存储在一个列表中,因此可以在列表推导式中重用它来构建行和标题(第一个项目没有标题,我只是留空了)。

现在它看起来像这样:

        count   pos     _pos    _neg
31022550        0       20      0       0
31022550        2       20      2       0
31022550        0       20      0       0

Python 3用户需要进行以下更改:

with open('mycsvfile.csv', 'wb') as f:

by

with open('mycsvfile.csv', 'w',newline="") as f:

并且

for k, vl in ids.iteritems():

by

for k, vl in ids.items():  # also works in python 2

请注意,writerow 的双循环可以被一个单一的、双循环的、扁平的生成器推导式替代,并传递给 writerows,以更快地执行。
writer.writerows([k] + [v[key] for key in keys] for k, vl in ids.items() for v in vl)

为什么不使用 csv.DictWriter() 呢? - Martijn Pieters
@MartijnPieters,使用DictWriter不是很好:1)标题行与键不符(id被写成空字符串),2)并非所有字典数据都被写入,这会在写入时创建一个错误ValueError: dict contains fields not in fieldnames - Jean-François Fabre
您可以使用空字段名称/键。并且您可以配置DictWriter忽略额外的键。 - Martijn Pieters
只需添加一个额外的键或建议OP在构建时将额外的键放入管道中即可 :-) - Martijn Pieters
那么?请注意,我在另一篇帖子中写了代码。可以将其调整为直接在那里添加密钥。OP甚至可以直接将行写出来,而不是收集到列表中。 - Martijn Pieters
显示剩余3条评论

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