0

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

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

文件 #1

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

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

RED|PINK 
ORANGE
BROWN|BLACK|GREEN|PURPLE
YELLOW|MAGENTA

我想解析每个文件并匹配相同的单词,然后也附加额外测量的列。但我想忽略///第一个文件中|的 和第二个文件中的 ,以便将每个单词单独与另一个列表进行比较。输出文件应该只有一列出现在两个列表中的任何单词,然后是文件 2 中附加的附加信息。有帮助吗?


添加信息/更新:

这是文件 #1 的 8 行,我在上面使用了颜色名称以使其更简单,但这才是真正的文字:这些是“符号”:

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

这是文件 #2 的一行:我需要做的是从 file1 运行每个符号,看看它是否与 file2 中第 5 列中的任何一个“同义词”匹配(这里的同义词是 A1B|ABG|间隙|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

File2 为 22,000 KB,文件 1 小得多。我曾想过像建议的那样创建一个字典,但我一直被每个文件中的不同分隔符所困扰。到目前为止,感谢大家提出的问题和帮助。

4

3 回答 3

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

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

    file1set = set(file1line.split(' /// '))

    file2set = set(file2line.split('|'))

    wordsineach = list(file1set & file2set)

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

set() 把它变成一个集合,这样我们就可以很容易地比较每一行的差异

  1. 循环“wordsineach”并写入您的新文件
于 2013-01-12T00:20:48.970 回答
0

编辑

在您在下面发表评论后,我认为这就是您想要做的。我已将原始帖子留在下面,以防万一其中的任何内容对您有用。

所以,我认为你想做以下事情。首先,此代码会将 file1 中的每个单独的同义词读入 a 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 寻找匹配:

with open("file2.txt", "r") as in_fd:
    with open("output.txt", "w") as out_fd:
        for line in in_fd:
            items = line.split("\t")
            if len(items) < 5:
                # This is so we don't crash if we find a line that's too short
                continue
            synonyms = set(i.strip() for i in items[4].split("|"))
            overlap = synonyms & file1_data
            if overlap:
                # Build string of columns from file2, stripping out 5th column.
                output_str = "\t".join(items[:4] + items[5:])
                for item in overlap:
                    out_fd.write("\t".join((item, output_str)))

所以它的作用是打开 file2 和一个输出文件。它遍历 file2 中的每一行,并首先检查它是否有足够的列以至少有第 5 列 - 如果没有,它会忽略该行(您可能想要打印错误)。

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

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

如果有重叠,我们构建一个字符串,它是我们要附加到同义词的完整列列表 - 即使有多个匹配项,我们也可以将其构建为一个字符串一次,因为每个匹配项都是相同的,因为它all 来自 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) 方法更有效的方法(即它在一个整个文件中运行的次数与另一个文件中的行数一样多),但这需要更详细有关如何匹配线条的信息。

例如,您可以构建一个字典,将一个单词映射到该单词出现的行列表 - 这使得检查匹配行比上面执行的完整扫描快得多。但是,由于您似乎想要行之间的重叠,这显得有些繁琐,因此我认为上面概述的简单方法就足够了,无需更多细节。

于 2013-01-12T00:30:42.280 回答
0

使用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')

然后使用列表理解

common_words = [i for i in content1 if i in content2]

但是,如果您已经知道每个文件中的单词都不相同,则可以使用设置交集来使生活更轻松

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)

至于您的“附加信息”,除非您告诉我们它的格式等,否则我无法为您提供帮助。

于 2013-01-12T00:24:16.203 回答