如何将 python 中 for 循环的输出写入 csv 格式的文件?

Posted

技术标签:

【中文标题】如何将 python 中 for 循环的输出写入 csv 格式的文件?【英文标题】:How can I write output from a for loop in python into a csv-formatted file? 【发布时间】:2015-10-16 06:35:47 【问题描述】:

以下是python脚本,用于识别是否在不同文件列表中找到了某些单词。

experiment=open('potentiation.txt')
lines=experiment.read().splitlines()
receptors=['crystal_1.txt', 'modeller_1.txt', 'moe_1.txt',
           'nci5_modeller0000_1.txt', 'nci5_modeller0001_1.txt',
           'nci5_modeller0002_1.txt', 'nci5_modeller0003_1.txt',
           'nci5_modeller0004_1.txt', 'nci5_modeller0005_1.txt',
           'nci5_modeller0006_1.txt', 'nci5_modeller0007_1.txt',
           'nci5_modeller0008_1.txt', 'nci5_modeller0009_1.txt',
           'nci5_modeller0010_1.txt', 'nci5_modeller0011_1.txt',
           'nci5_moe0000_1.txt', 'nci5_moe0001_1.txt', 'nci5_moe0002_1.txt',
           'nci5_moe0003_1.txt', 'nci5_moe0004_1.txt', 'nci5_moe0005_1.txt',
           'nci5_moe0006_1.txt', 'nci5_moe0007_1.txt', 'nci5_moe0008_1.txt',
           'nci5_moe0009_1.txt', 'nci5_moe0010_1.txt', 'nci5_moe0011_1.txt',
           'nci5_moe0012_1.txt', 'nci5_moe0013_1.txt', 'nci5_moe0014_1.txt']

for ligand in lines:
    for protein in receptors:
        file1=open(protein,"r")
        read1=file1.read()
        find_hit=read1.find(ligand)
        if find_hit == -1:
            print ligand,protein,"Not Found"
        else:
            print ligand,protein, "Found"

此代码的输出示例如下:

345647 nci5_moe0012_1.txt Not Found
345647 nci5_moe0013_1.txt Not Found
345647 nci5_moe0014_1.txt Found

我的问题是如何获取输出并将其格式化为如下示例所示的 csv 文件?

Ligand  nci5_moe0012_1. nci5_moe_0013_1   nci5_moe_0014
345647  Not Found        Not Found        Found

【问题讨论】:

【参考方案1】:

在将“蛋白质”和“配体”的值添加到适当的列表(在 0 索引中)后,您可以将结果保存在列表中(一个列表用于配体,一个用于蛋白质)。之后很容易将其保存为文本文件。 为了保存您打开一个文件以在字符串中写入和转换列表:

my_string = " ".join(map(str, lst))

然后保存 my_string (并为每个列表执行此操作)

【讨论】:

或者你可以使用字典(键是配体,值是元组(file, Found/Not Found) 感谢您的回复。我对python很陌生。您能否详细解释一下如何将两个不同的列表写入单个文本文件并包含输出数据(找到或未找到)? 是不是更容易理解?您可以在 join 方法中使用“,”(在 csv 中更多)。 好的,还有一个问题,如何将两个列表保存为一个文本文件? 这里,这不是列表而是字符串!!【参考方案2】:

我认为这样可以做到(假设您的输出文件是制表符分隔的):

import csv
import os

receptors = ['crystal_1', 'modeller_1', 'moe_1',
             'nci5_modeller0000_1', 'nci5_modeller0001_1',
             'nci5_modeller0002_1', 'nci5_modeller0003_1',
             'nci5_modeller0004_1', 'nci5_modeller0005_1',
             'nci5_modeller0006_1', 'nci5_modeller0007_1',
             'nci5_modeller0008_1', 'nci5_modeller0009_1',
             'nci5_modeller0010_1', 'nci5_modeller0011_1',
             'nci5_moe0000_1', 'nci5_moe0001_1', 'nci5_moe0002_1',
             'nci5_moe0003_1', 'nci5_moe0004_1', 'nci5_moe0005_1',
             'nci5_moe0006_1', 'nci5_moe0007_1', 'nci5_moe0008_1',
             'nci5_moe0009_1', 'nci5_moe0010_1', 'nci5_moe0011_1',
             'nci5_moe0012_1', 'nci5_moe0013_1', 'nci5_moe0014_1']

with open('potentiation.txt', 'rt') as experiment, \
     open('output.csv', 'wb') as outfile:
    csv_writer = csv.writer(outfile, delimiter='\t')
    csv_writer.writerow(['Ligand'] + receptors)  # header row
    for ligand in (line.rstrip() for line in experiment):
        row = [ligand]
        for protein in receptors:
            with open(protein+'.txt', "rt") as file1:
                found = ['Found', 'Not Found'][file1.read().find(ligand) == -1]
                row.append(found)
        csv_writer.writerow(row)

print('output.csv file written')

更新

正如我在评论中所说,只需读取一次蛋白质文件,这可以更快地完成。为了能够做到这一点并按照您想要的方式格式化输出,检查每个文件中每个配体的结果需要存储在一个数据结构中,随着每个文件被读取然后多次检查,这些数据结构会逐渐增加,只为了写出来,一次全部完成,毕竟已经完成了。一个简单的 list-of-lists 足以满足此目的,并已在下面的实现中使用。

权衡是使用更多内存而不是一遍又一遍地读取和重新读取蛋白质文件。由于磁盘 IO 通常是计算机上最慢的事情之一,因此仅略微增加代码复杂度就可能获得巨大的性能提升可能是值得的。

这是显示此替代版本的代码:

import csv
import os

receptors = ['crystal_1', 'modeller_1', 'moe_1',
             'nci5_modeller0000_1', 'nci5_modeller0001_1',
             'nci5_modeller0002_1', 'nci5_modeller0003_1',
             'nci5_modeller0004_1', 'nci5_modeller0005_1',
             'nci5_modeller0006_1', 'nci5_modeller0007_1',
             'nci5_modeller0008_1', 'nci5_modeller0009_1',
             'nci5_modeller0010_1', 'nci5_modeller0011_1',
             'nci5_moe0000_1', 'nci5_moe0001_1', 'nci5_moe0002_1',
             'nci5_moe0003_1', 'nci5_moe0004_1', 'nci5_moe0005_1',
             'nci5_moe0006_1', 'nci5_moe0007_1', 'nci5_moe0008_1',
             'nci5_moe0009_1', 'nci5_moe0010_1', 'nci5_moe0011_1',
             'nci5_moe0012_1', 'nci5_moe0013_1', 'nci5_moe0014_1']

# initialize list of lists holding each ligand and its presence in each receptor
with open('potentiation.txt') as experiment:
    ligands = [[ligand] for ligand in (line.rstrip() for line in experiment)]

for protein in receptors:
    with open(protein + '.txt') as protein_file:
        protein_file_data = protein_file.read()
        for row in ligands:
            # determine if this ligand (row[0]) appears in protein data
            row.append('Found' if row[0] in protein_file_data else 'Not Found')

with open('output.csv', 'wb') as outfile:
    csv_writer = csv.writer(outfile, delimiter='\t')
    csv_writer.writerow(['Ligand'] + receptors)  # header row
    csv_writer.writerows(ligands)

print('output.csv file written')

【讨论】:

谢谢!当我使用此代码时,我收到以下错误消息: csv_writer([ligand, protein, "Found" if found else "Not Found"]) TypeError: '_csv.writer' object is not callable。有什么建议吗? 感谢这项工作!还有一个问题。 ^M 是什么意思?它出现在每个 protein_file 之后的输出 csv 中?有没有办法摆脱它? 这是一个回车符。我的最后一次更新可能会摆脱它。如果没有,可能是因为您使用的是 Python 3,但没有在您的问题中指定(应该让我知道)。 Adam:重读您的问题后,我意识到我的回答只是将循环输出转换为 csv 格式,而不是按照您想要的方式排列。我的最新更新应该可以纠正这一点。 感谢您的关注。脚本实际上还有一个问题。该脚本用于查找是否在各种蛋白质文件中找到了某个配体。但是,脚本的输出当前显示每个蛋白质文件的所有配体的“未找到”。这是不正确的,因为应该有一些“找到”和一些“未找到”。我认为一个简单的条件表达式应该可以工作。如何最好地将其引入脚本中?

以上是关于如何将 python 中 for 循环的输出写入 csv 格式的文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 for 循环输出写入 csv 文件?

将for循环的输出写入多个文件

Python - 写入 CSV 文件和 for 循环

求解python如何通过for循环将字符串的值放到一个列表中

如何将创建多个字典的 for 循环的输出加入/合并到一个大字典中

C++ 如何将一个文件里的数据写入到另一个文件里?