【问题标题】:Merging two files by one common set of identifiers with python使用python通过一组常见的标识符合并两个文件
【发布时间】:2015-10-03 01:49:50
【问题描述】:

我想合并共享一个公共列的两个制表符分隔的文本文件。我有一个看起来像这样的“标识符文件”(2 列 x 1050 行):

module 1 gene 1
module 1 gene 2
..
module x gene y

我还有一个制表符分隔的“目标”文本文件,看起来像这样(36 列 x 12000 行):

gene 1 sample 1 sample 2 etc
gene 2 sample 1 sample 2 etc
..
gene z sample 1 sample 2 etc

我想根据基因标识符合并这两个文件,并从标识符和目标文件中获得匹配的表达值和模块隶属关系。本质上是从标识符文件中获取基因,在目标文件中找到它们并创建一个新文件,其中包含模块#、基因#和表达值都在一个文件中。欢迎提出任何建议。

我想要的输出是由制表符分隔的基因 ID 选项卡模块隶属关系选项卡样本值。

这是我想出的脚本。编写的脚本不会产生任何错误消息,但它给了我一个空文件。

expression_values = {}          
matches = []  
   with open("identifiers.txt") as ids, open("target.txt") as target:  
         for line in target:
             expression_values = {line.split()[0]:line.split()}
         for line in ids:
             block_idents=line.split()
         for gene in expression_values.iterkeys():    
             if gene==block_idents[1]:
                  matches.append(block_idents[0]+block_idents[1]+expression_values)  
csvfile = "modules.csv"  
with open(csvfile, "w") as output:
    writer = csv.writer(output, lineterminator='\n')
    for val in matches:
        writer.writerow([val])  

谢谢!

【问题讨论】:

    标签: python merge


    【解决方案1】:

    这些代码行并没有按照您的预期执行:

    for line in target:
        expression_values = {line.split()[0]:line.split()}
    for line in ids:
        block_idents=line.split()
    for gene in expression_values.iterkeys():    
        if gene==block_idents[1]:
            matches.append(block_idents[0]+block_idents[1]+expression_values)
    

    表达式值和 block_idents 将仅根据您正在更新它们的文件的当前行具有值。换句话说,字典和列表并没有随着更多的行被读取而“增长”。也可以使用 csv 模块轻松解析 TSV 文件。

    我对这个粗略的解决方案做了一些假设:

    1. 第一个文件中的“基因”是唯一会出现的“基因” 在第二个文件中。
    2. 第一个文件中可能存在重复的“基因”。

    首先构造第一个文件中数据的映射为:

    import csv
    from collections import defaultdict
    gene_map = defaultdict(list)
    with open(first_file, 'rb') as file_one:
        csv_reader = csv.reader(file_one, delimiter='\t')
        for row in csv_reader:
            gene_map[row[1]].append(row[0])
    

    同时读取第二个文件并写入输出文件。

    with open(sec_file, 'rb') as file_two, open(op_file, 'w') as out_file:
        csv_reader = csv.reader(file_two, delimiter='\t')
        csv_writer = csv.writer(out_file, delimiter='\t')
        for row in csv_reader:
            values = gene_map.get(row[0], [])
            op_list = []
            op_list.append(row[0])
            op_list.extend(values)
            values.extend(row[1:])
            csv_writer.writerow(op_list)
    

    【讨论】:

    • 谢谢您,您编写的脚本有效。顺便说一句,第一个文件中没有重复项。此外,第一个文件中的基因并不是唯一出现在第二个文件中的基因。目标是将模块从属关系从文件 1 附加到文件 2 中的正确基因。
    • 我认为上面的代码会因为defaultdict(list)而工作,无论重复。 gene_map 字典中的 get 负责处理第一个文件中尚未遇到的任何新基因。
    【解决方案2】:

    现有方法存在许多问题,其中最重要的是您丢弃了文件中除了每个文件的最后一行之外的所有数据。每个“for line in”下的赋值都会替换变量的内容,所以只有最后一行的最后一个赋值才会生效。

    假设每个基因只出现在一个模块中,我建议您将“ids”读入字典,为每个基因保存模块:

    geneMod = {}
    for line in ids:
       id = line.split()
       geneMod[ id[0] ] = id[1] 
    

    然后你可以遍历目标行,对每一行进行拆分,获取基因 id gene= targetsplit[0] 并保存(或输出)相同的拆分字段但插入模块值,例如:print gene, geneMod[gene], targetsplit[1:]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-05
      • 2021-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多