好的,所以我是新手,这是我的问题: 我有两个文件,一个包含基因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%
我不确定最好的方法,任何建议都表示赞赏!文件相当大,因此速度是个问题。谢谢!
答案 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()
。
所以你的任务基本上由以下部分组成:
format()
)。有帮助吗?你有什么问题吗?
答案 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)。