为世界上的Perl大师干杯!
我有一个像这样的文件要解析,并且想要生成......
从第一列开始,ID,外显子信息,起始位置,结束位置和方向。ID在遇到一个数字时加1。
1 9239 712 8571 +
1 start_codon 712 714 +
1 stop_codon 8569 8571 +
2 3882 24137 24264 +
2 start_codon 24137 24139 +
3 3882 24322 24391 +
4 3882 24490 26064 +
4 stop_codon 26062 26064 +
5 4972 26704 26740 +
5 start_codon 26704 26706 +
6 4972 26814 27170 +
7 4972 27257 27978 +
7 stop_codon 27976 27978 +
8 10048 40161 41114 -
8 start_codon 41112 41114 -
8 stop_codon 40161 40163 -
9 272 43167 43629 -
9 stop_codon 43167 43169 -
10 272 43755 44059 -
10 start_codon 44057 44059 -像这样....
1 9239 *712* *8571* +
1 start_codon 712 714 +
1 stop_codon 8569 8571 +
*X 9239 712 8571 +*
2 3882 *24137* 24264 +
2 start_codon 24137 24139 +
3 3882 24322 24391 +
4 3882 24490 *26064* +
4 stop_codon 26062 26064 +
*X 3882 24173 26064 +*
5 4972 *26704* 26740 +
5 start_codon 26704 26706 +
6 4972 26814 27170 +
7 4972 27257 *27978* +
7 stop_codon 27976 27978 +
*X 4972 26704 27978 +*
8 10048 *40161* *41114* -
8 start_codon 41112 41114 -
8 stop_codon 40161 40163 -
*X 10048 40161 41114 -*
9 272 *43167* 43629 -
9 stop_codon 43167 43169 -
10 272 43755 *44059* -
10 start_codon 44057 44059 -
*X 272 43167 44059 -*每一行都以X开头,必须添加,但以我的技能我不能…:(
问题是,对于第二列中忽略"start_codon“和"end_codon”的每个外显子编号,必须获得星号*之间的最小编号外显子位置和最大编号外显子位置。
这是我解析数据的基本代码...但我想,必须从头开始重新编码(我不知道如何插入行'X')
(很抱歉,我删除了代码,因为它不够好,可能会造成混乱……)
世界上的Perl大师们,能帮帮我吗?
谢谢你!!
当TLP崩溃时,我把代码放回去了。尽管它的代码令人尴尬
use strict;
if (@ARGV != 1) {
print "Invalid arguments\n";
print "Usage: perl min_max.pl [exon_output_file]\n";
exit(0);
}
my $FILENAME = $ARGV[0];
my $exonid = 0;
my $exon = "";
my $startpos = 0;
my $endpos = 0;
my $strand = "";
my $min_pos = 0;
my $max_pos = 0;
open (DATA, $FILENAME);
while (my $line = <DATA>) {
chomp $line;
if ($line ne "") {
if ($line =~ /^(.+)\t(.+)\t(.+)\t(.+)\t(.+)/) {
$exonid = $1;
$exon = $2;
$startpos = $3;
$endpos = $4;
$strand = $5;
}
if ($exon =~ /\d+/) {
print $exonid,"\t",$exon,"\t",$startpos,"\t",$endpos,"\t",$strand,"\n";
} else {
print $exonid,"\t",$exon,"\t",$startpos,"\t",$endpos,"\t",$strand,"\n";
}
}
}
close (DATA);
exit;如何比较最大值和最低值...
发布于 2012-12-26 21:09:56
基本上你要做的就是遍历这些行,跳过那些你不需要的行(即第二列中没有数字),记住同一集合中每一新行的最小/最大值,当第二列的数字发生变化时,你会打印并重新开始。使用此解决方案,您还必须在最后手动打印最后一组。
此代码将内部DATA文件句柄用于演示数据。只需将<DATA>更改为<>即可在目标输入文件上使用,如下所示:perl script.pl inputfile
use strict;
use warnings;
use List::Util qw(min max);
my $print;
my ($min, $max, $id);
while (<DATA>) { ###### change to <> to run on input file
my @line = split;
if ($line[1] !~ /^\d+$/) { # if non-numbers in col 2
print; # print line
next; # skip to next line
}
if (!defined($id) or $id != $line[1]) { # New dataset!
say $print if $print; # Print and reset
$id = $line[1];
$min = $max = undef;
}
$min = min($min // (), @line[2,3]); # find min/max, skip undef
$max = max($max // (), @line[2,3]);
$print = join "\t", "X", $line[1], $min, $max; # buffer the print
}
print $print;
__DATA__
1 9239 712 8571 +
1 start_codon 712 714 +
1 stop_codon 8569 8571 +
2 3882 24137 24264 +
2 start_codon 24137 24139 +
3 3882 24322 24391 +
4 3882 24490 26064 +
4 stop_codon 26062 26064 +
5 4972 26704 26740 +
5 start_codon 26704 26706 +
6 4972 26814 27170 +
7 4972 27257 27978 +
7 stop_codon 27976 27978 +
8 10048 40161 41114 -
8 start_codon 41112 41114 -
8 stop_codon 40161 40163 -
9 272 43167 43629 -
9 stop_codon 43167 43169 -
10 272 43755 44059 -
10 start_codon 44057 44059 -输出:
9239 712 8571
3882 24137 26064
4972 26704 27978
10048 40161 41114
272 43167 44059发布于 2012-12-26 20:34:10
如果我没理解错的话,这里有一种方法(未经测试!)去做你似乎在请求的事情:
use strict;
use warnings;
use feature 'say';
# read first line, initialize accumulators, print it back
chomp($_ = <>);
my ($last_id, $last_exon, $min_start, $max_end, $last_strand) = split /\t/;
say $_;
# loop over remaining lines
while (<>) {
chomp;
my ($exonid, $exon, $startpos, $endpos, $strand) = split /\t/;
if ($exon !~ /\D/ and $exon != $last_exon) {
# new exon found, print summary of last one...
say join "\t", "X", $last_exon, $min_start, $max_end, $last_strand;
# ...and reset accumulators
($last_id, $last_exon, $min_start, $max_end, $last_strand)
= ($exonid, $exon, $startpos, $endpos, $strand);
}
else {
# previous exon continues, just update accumulators
$last_id = $exonid;
$last_exon = $exon if $exon !~ /\D/;
$min_start = $startpos if $min_start > $startpos;
$max_end = $endpos if $max_end < $endpos;
$last_strand = $strand; # should not really be needed
}
# ...and don't forget to print the original line back again
say $_;
}
# end of file, print summary of last exon
print join("\t", "X", $last_exon, $min_start, $max_end, $last_strand), "\n";基本上,我假设每当在第二列中遇到与该列中的前一个数字不同的数字时,都要打印一个以X开头的摘要行,并且第二列中包含非数值的行永远不会触发摘要。此外,您可能还需要在文件的末尾添加一个摘要行。
如果$exon仅包含数字,则表达式$exon !~ /\D/返回true。(具体地说,它会测试它是否不包含非数字字符,因此空字符串也会匹配。)
有一堆我没有考虑过的边缘情况,因为我不知道它们在你的数据中是否可能出现,以及如果它们确实发生了,你想如何处理它们。例如,为了谨慎起见,人们可能还希望在不太可能的情况下打印摘要,即在外显子数量保持不变的情况下链发生变化。类似地,细心的程序员可能希望考虑输入文件为空的可能性,或者第一行在第二列中包含非数字值的可能性。
至少在use warnings中,如果我假设的任何数值都是数值,结果却不是这样,您会收到警告。
https://stackoverflow.com/questions/14039330
复制相似问题