删除文件每行中不需要的字符,然后在Python中将剩下的字符匹配到另一个文件中

2024-06-11 11:38:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我想写一个python脚本来解决以下问题:

我有两个制表符分隔的文件,一个只有一列各种单词。另一个文件有一列包含相似的单词,以及其他信息列。但是,在第一个文件中,有些行包含多个单词,用“//”分隔。另一个文件也有类似的问题,但分隔符是“|”。在

文件1

RED
BLUE /// GREEN
YELLOW /// PINK /// PURPLE
ORANGE
BROWN /// BLACK

文件#2(其中包含其他测量的附加列)

^{pr2}$

我想解析每个文件并匹配相同的单词,然后再附加额外度量的列。但是我想忽略第一个文件中的///,而第二个文件中的|,这样每个单词都可以单独与其他列表进行比较。输出文件应该只包含两个列表中出现的任何单词的一列,然后是来自文件2的附加信息。有什么帮助吗??在


添加信息/更新:

这里有8行文件#1,我使用了上面的颜色名称使它更简单,但这是真正的单词:这些是“符号”:

ANKRD38  
ANKRD57  
ANKRD57
ANXA8 /// ANXA8L1 /// ANXA8L2  
AOF1  
AOF2  
AP1GBP1  
APOBEC3F /// APOBEC3G  

这里有一行文件#2:我需要做的是运行文件1中的每个符号,看看它是否与文件2中第5列中的“同义词”匹配(这里的同义词是A1B | ABG | GAP | HYST2477)。如果file1中的任何符号与col 5文件2中的任何同义词匹配,那么我需要将附加信息(file2中的其他列)附加到file1中的符号上,并创建一个大的输出文件。在

9606  '\t'    1 '\t'    A1BG  '\t'   -   '\t'       A1B|ABG|GAB|HYST2477'\t'    HGNC:5|MIM:138670|Ensembl:ENSG00000121410|HPRD:00726    '\t' 19   '\t'  19q13.4'\t' alpha-1-B glycoprotein '\t' protein-coding '\t' A1BG'\t'    alpha-1-B glycoprotein'\t'  O '\t'  alpha-1B-glycoprotein '\t'  20120726

文件2是22000 KB,文件1要小得多。我曾经想过创建一个dict,就像我们建议的那样,但是我一直被每个文件中不同的分隔符所困扰。感谢大家的提问和帮助。在


Tags: 文件alpha信息列表符号单词file1分隔符
3条回答

编辑

在你的评论之后,我想这就是你想做的。我留下了下面的原始帖子,以防有什么对你有用。在

所以,我想你应该做以下事情。首先,这段代码将从file1将每个单独的同义词读入set-这是一个有用的结构,因为它会自动删除任何重复项,并且查找起来非常快。它就像一本字典,但只有键,没有值。如果您不想删除重复项,我们需要稍微改变一下。在

file1_data = set()
with open("file1.txt", "r") as fd:
    for line in fd:
        file1_data.update(i.strip() for i in line.split("///") if i.strip())

然后,您需要运行file2以查找匹配项:

^{pr2}$

这样做的是打开file2和一个输出文件。它遍历file2中的每一行,首先检查它是否有足够的列以至少有一列5—如果没有,它将忽略该行(您可能需要打印一个错误)。在

然后它按|拆分第5列,并从该列表中构建一个set(称为synonyms)。set很有用,因为我们可以很快地找到它与file1中所有同义词的前一组的交集,这个交集存储在overlap中。在

然后我们要做的是检查是否有任何重叠-如果没有,我们忽略这一行,因为在file1中没有找到同义词。这个检查主要是为了速度,所以如果我们不打算在这行中使用输出字符串,我们就不必费心构建输出字符串。在

如果有重叠,我们构建一个字符串,它是我们要附加到同义词的列的完整列表-我们可以将它作为字符串构建一次,即使有多个匹配项,因为每个匹配项都是相同的,因为它都来自file2中的行。这比每次将其构建为字符串要快。在

然后,对于file1中匹配的每个同义词,我们向输出写入一行同义词,然后是一个制表符,然后是file2中该行的其余部分。因为我们按制表符分割,所以我们必须用"\t".join(...)将它们放回原处。这是假设我是正确的,你想删除第5列-如果你不想删除它,那么它就更容易了,因为你可以使用file2中的行,在末尾去掉新行。在

希望这更接近你的需要?在

原帖

你没有给出文件大小的任何指示,但是我会假设它们足够小,可以放入内存中——如果没有,你的问题就变得稍微棘手了。在

因此,第一步可能是打开文件2并读入数据。你可以用这样的代码来实现:

file2_data = {}
with open("file2.txt", "r") as fd:
    for line in fd:
        items = line.split("\t")
        file2_data[frozenset(i.strip() for i in items[0].split("|"))] = items[1:]

这将创建file2_data作为一个字典,它将一个单词映射到该行中剩余项的列表中。正如我在前面的评论中提到的,你还应该考虑单词是否可以重复,以及你希望如何处理。在

之后,您可以读取第一个文件并将数据附加到该文件中的每个单词:

with open("file1.txt", "r") as fd:
    with open("output.txt", "w") as fd_out:
        for line in fd:
            words = set(i.strip() for i in line.split("///"))
            for file2_words, file2_cols in file2_data.iteritems():
                overlap = file2_words & words
                if overlap:
                    fd_out.write("///".join(overlap) + "\t" + "\t".join(file2_cols))

最后,output.txt中的每一行都是两个文件中的单词列表至少有一个共同的单词,第一项是用///分隔的单词。输出文件中的其他列将是文件2中匹配行中的其他列。在

如果这不是你想要的,你需要更具体一点。在

顺便说一句,可能有比我上面概述的O(N^2)方法更有效的方法(即,它在一个完整的文件中运行的次数与另一个文件中的行数相同),但这需要关于如何匹配行的更详细的信息。在

例如,您可以构造一个字典,将一个单词映射到该单词所在的行的列表中,这使得检查匹配行的速度比上面执行的完整扫描快得多。但是,由于您似乎想要行之间的重叠,所以我认为上面概述的简单方法就足够了没有更多细节。在

  1. 查看文件i/o的http://docs.python.org/2/tutorial/inputoutput.html

  2. 循环遍历每个文件中的每一行

    file1set=设置(file1线.分割(“///”)

    file2set=设置(file2线.分割(“|”))

    wordsineach=列表(file1set&file2set)

split将创建一个颜色名称数组

set()将它转换为一个集合,这样我们就可以轻松地比较每一行中的差异

  1. 循环“wordsineach”并写入新文件

使用str.replace函数

with open('file1.txt', 'r') as f1:
    content1 = f1.read()
    content1 = content1.replace(' /// ', '\n').split('\n')
with open('file2.txt', 'r') as f2:
    content2 = f2.read()
    content2 = content1.replace('|', '\n').split('\n')

然后使用列表理解

^{pr2}$

但是,如果您已经知道每个文件中的单词都不相同,则可以使用set intersections来简化操作

common_words = list(set(content1) & set(content2))

然后将余数输出到另一个文件:

common_words = [i + '\n' for i in common_words]  #so that we print each word on a new line

with open('common_words.txt', 'w') as f:
    f.writelines(common_words)

至于你的“附加信息”,除非你告诉我们它是如何格式化的,否则我无法帮助你

相关问题 更多 >