如何在文件中搜索perl或python中某个范围内的所有位置?

时间:2011-12-07 04:19:06

标签: python perl

好的,所以我是新手,这是我的问题: 我有两个文件,一个包含基因ID和一个带有开始和停止位置的范围:例如:

gene_id start stop 
grf4      1245  1365
fgt89     3089  4524
tig3      45600 46800

另一个包含有关这些职位的职位和信息,例如:

position   nucleotide  %support
3980         T          98%
456          C          78%
45900        G          100%
4234         C          70%

我想生成一个文件,其中包含每个gene_id的一行以及第二个文件中属于该基因的所有信息,例如:

gene_id  start  stop position nucleotide support
fgt89    3089    4524  3980    T         98%
fgt89    3089    4524  4234    C         70%
tig3     45600   46800 45900   G         100% 

我不确定最好的方法,任何建议都表示赞赏!文件相当大,因此速度是个问题。谢谢!

3 个答案:

答案 0 :(得分:3)

将文本更改为数据

首先,我建议处理您的文件并将其保存为数据库,以便于进一步处理。您可以从这些文件中提取数据,例如。通过以下方式:

file1 = open('some_filename.txt')
file1_lines = [filter(len, line.split(' ')) for line in file1.readlines()]

并且file1_lines将包含与此类似的内容:

  

[['gene_id','start','stop'],['grf4','1245','1365'],['fgt89','3089','4524'],['tig3' ,'45600','46800']]

表示您现在可以将数据插入数据库。

将数据插入数据库

您现在应该将数据插入到数据库中,以便使用适当的工具(在本例中为RDBMS)轻松处理。我建议使用SQLite(参见sqlite3 built-in module for Python)。如果您不了解SQL,请询问有关它的具体问题。但我相信数据库是最适合您任务的形式。

从数据库中提取您需要的数据

在数据库中存储数据后,可以轻松获取所需数据。查询可能看起来像那样(查询显然没有经过测试,但看起来没问题,如果名称与数据库中的名称匹配,则应该符合您的需求):

SELECT `ranges`.`gene_id`, `ranges`.`start`, `ranges`.`stop`,
    `nucleotides`.`position`, `nucleotides`.`nucleotide`, `nucleotides`.`support`
FROM `ranges`
JOIN `nucleotides`
ON (
    (`ranges`.`start` < `nucleotides`.`position`)
    AND
    (`nucleotides`.`position` < `ranges`.`start`)
)
ORDER BY `ranges`.`gene_id` ASC, `nucleotides`.`position` ASC

这将按照gene_id升序,然后position升序的顺序为您提供所需的数据。

剩下的唯一任务是将数据输出到文件中。我建议使用format()

摘要

所以你的任务基本上由以下部分组成:

  1. 将文本(文件内容)转换为数据(变量列表)。
  2. 使用适当的结构创建数据库。
  3. 将文件中的数据插入数据库(确保整数和浮点数存储为数据,而不是字符串)。
  4. 如上所述,对数据库进行查询。
  5. 如有必要,将数据作为文本输出到文件中(使用字符串格式 - format())。
  6. 有帮助吗?你有什么问题吗?

答案 1 :(得分:1)

课程数据库是Tadeck发布的理想解决方案,但您可以尝试

>>> def Test():
    fin1=open("file1.txt") #File as per your First Table
    fin2=open("file2.txt") #File as per your Second Table
    fin1.readline()        #Skip the Header
    fin2.readline()        #Skip the Header
    #Sort The First list and create an Iterator
    data1=iter(sorted([[f.split()[1],f.split()[2],f.split()[0]] 
               for f in fin1.xreadlines()], key=operator.itemgetter(0)))  
    #Sort The Second List and create an Iterator
    data2=iter(sorted([f.split() for f in fin2.xreadlines()],
               key=operator.itemgetter(0))) 
    #Print The Header
    print "{0:10}{1:10}{2:10}{3:10}{4:10}{5:10}".format("gene_id",
                                                        "start",
                                                        "stop",
                                                        "position",
                                                        "nucleotide",
                                                        "support") 
    try:
        v1=data1.next() #Read First Item from First List
        v2=data2.next() #Read Second Item from First List
        while True: #Loop Until One of the List has reached the end
            #If the Position is greater than stop range (from first list), 
            #read the next item from the first list
            if v2[0] > v1[1]: 
                 v1=data1.next() 
            #If the Position is greater or equal than the start range 
            #(We are in the range)
            elif v2[0] >= v1[0]: 
                #Format and Print it
                print "{0:10}{1:10}{2:10}{3:10}{4:10}{5:10}".format(v1[2],
                                                                    v1[0],
                                                                    v1[1],
                                                                    v2[0],
                                                                    v2[1],
                                                                    v2[2]) 
                #Read the Next Item From the Second List
                v2=data2.next() 
            #Not in any Range so Read the Next Item From the Second List
            else: v2=data2.next() 
    except StopIteration:
        None


>>> Test()
gene_id   start     stop      position  nucleotidesupport   
fgt89     3089      4524      3980      T         98%       
fgt89     3089      4524      4234      C         70%       
tig3      45600     46800     45900     G         100%      
>>> 

答案 2 :(得分:0)

简单的Perl解决方案可能如下所示:

#!/usr/bin/perl
use warnings;
use strict;

open my $F2, '<', '8410347-file2.txt' or die $!;
my %at_position;
while (<$F2>) {
    my ($position, $nucleotide, $support) = split;
    warn "Duplicate position $position\n" if exists $at_position{$position};
    $at_position{$position} = {nucleotide => $nucleotide,
                               support    => $support};
}
close $F2;

open my $F1, '<', '8410347-file1.txt' or die $!;
while (<$F1>) {
    my ($id, $start, $stop) = split;
    my @matches = grep $_ >= $start && $_ <= $stop, keys %at_position;
    for my $match (@matches) {
        print join("\t",
                   $id,
                   $start,
                   $stop,
                   $match,
                   $at_position{$match}{nucleotide},
                   $at_position{$match}{support},
                  ), "\n";
    }
}

如果您的文件很大,这种方法会太慢,并且需要一些更复杂的结构来捕获间隔(例如,请参阅Lazy Manager's Calendar)。