Chinaunix
标题:
perl 随机抽取文件中的一部分行
[打印本页]
作者:
niuguohao
时间:
2018-12-22 17:25
标题:
perl 随机抽取文件中的一部分行
本帖最后由 niuguohao 于 2018-12-22 17:28 编辑
有一个基因组vcf文件,里面位点非常多(每个位点一行),现在想从这些位点中按照染色体上的位置,每500bp范围内随机抽取一个位点出来(比如下面在scaffold1中属于1-500位置的是前四行,然后从中抽一行,属于501-1000的是5,6,7三行,再从中随机抽出一行,以此类推),想了半天不知道该如何实现。
vcf文件格式如下(tab分隔):
scaffold1 127 . C T 45.23 PASS AC=2 ;AF=0.011;=-……(后面还有很多故省略)
scaffold1 167 . G A 696.19 PASS AC=4 ;AF=0.02 2;0.……
scaffold1 260 . A G 1278.59 PASS AC=23 ;AF=0.1 11;5
scaffold1 462 . T C 4409.63 PASS AC=49 ;AF=0.2 33;……
scaffold1 636 . A G 7061.50 PASS AC=45 ;AF=0.2 12;=……
scaffold1 862 . C T 414.11 PASS AC=7 ;AF=0.03 3;;……
scaffold2 999 . G A 1135.55 PASS AC=4 ;AF=0.0 1949
scaffold2 128 . C T 45.23 PASS AC=2 ;AF=0.011 ;AN==-……
scaffold2 167 . G A 696.19 PASS AC=4 ;AF=0. 022; AN=oeff=0.
scaffold2 699 . A G 7061.50 PASS AC=45; AF=0.2 12;AN;DP=……
scaffold2 888 . C T 414.11 PASS AC=7 ;AF= 0.03 3;AN=;……
scaffold2 997 . G A 1135.55 PASS AC=4 ;AF=0.01 9;AN……
……
第一列是染色体名称 第二列是在该上染色体上的位置,后面是说明。
求助各位大神,应该如何操作呢?
作者:
523066680
时间:
2018-12-23 16:14
暂时先这样。
my %hash;
for my $line ( <DATA> )
{
next unless ( $line=~/(\w+)\s+(\w+)/ );
#next unless ( $1 eq "scaffold1" );
chomp $line;
if ( $2 > 1 and $2 <= 500 ) {
push @{$hash{ $1 }{'part1'}}, $line;
}
elsif ( $2 > 500 and $2 <= 1000 ) {
push @{$hash{ $1 }{'part2'}}, $line;
}
}
my $part1 = $hash{'scaffold1'}{'part1'};
my $part2 = $hash{'scaffold1'}{'part2'};
printf "%s\n", $part1->[rand($#{$part1}+1)];
printf "%s\n", $part2->[rand($#{$part2}+1)];
__DATA__
scaffold1 127 . C T 45.23 PASS AC=2 ;AF=0.011;=-...
scaffold1 167 . G A 696.19 PASS AC=4 ;AF=0.02 2;0....
scaffold1 260 . A G 1278.59 PASS AC=23 ;AF=0.1 11;5
scaffold1 462 . T C 4409.63 PASS AC=49 ;AF=0.2 33;...
scaffold1 636 . A G 7061.50 PASS AC=45 ;AF=0.2 12;=...
scaffold1 862 . C T 414.11 PASS AC=7 ;AF=0.03 3;;...
scaffold2 999 . G A 1135.55 PASS AC=4 ;AF=0.0 1949
scaffold2 128 . C T 45.23 PASS AC=2 ;AF=0.011 ;AN==-...
scaffold2 167 . G A 696.19 PASS AC=4 ;AF=0. 022; AN=oeff=0.
scaffold2 699 . A G 7061.50 PASS AC=45; AF=0.2 12;AN;DP=...
scaffold2 888 . C T 414.11 PASS AC=7 ;AF= 0.03 3;AN=;...
scaffold2 997 . G A 1135.55 PASS AC=4 ;AF=0.01 9;AN...
复制代码
作者:
niuguohao
时间:
2018-12-23 19:04
回复
2#
523066680
多谢大神指点,但是我这个文件的第二列数字还有很多大于1000的,最大的可能有6,7位数,有什么办法改改么?
作者:
hztj2005
时间:
2018-12-23 20:14
本帖最后由 hztj2005 于 2018-12-28 09:39 编辑
<div class="blockcode"><blockquote>
复制代码
use List::Util qw/min/;
use utf8;
my @datasource=(
["scaffold1","127",],
["scaffold1","167",],
["scaffold1","260",],
["scaffold1","462",],
["scaffold1","636",],
["scaffold1","862",],
["scaffold1","999",],#原数据此行scaffold2似有误
["scaffold2","128",],
["scaffold2","167",],
["scaffold2","699",],
["scaffold2","888",],
["scaffold2","997",],
);
my $sumline = @datasource;#行数
print $sumline."\n";;
my $endstr =$datasource[$#datasource][0];
if($endstr =~ /(\d+)/)
{
$scasum = $1;#染色体数量
#print $scasum."\n";
}
srand;#要先宣告srand函数,才能产生随机数的效果
my @onesca = ();
my $scastart =0;
my $scaend =0;
for(my $k=1;$k<$scasum+1;$k++)
{
my $maxvalue = -1;#该染色体最大位点
for(my $j=$scastart;$j<$sumline;$j++)
{
my $endstr2 =$datasource[$j][0];
#print "-- $endstr2\n"; #
if($endstr2 =~ /(\d+)/)
{
$scaid = $1;#染色体序号
if($scaid == $k)
{
push @onesca,$datasource[$j][1];
$maxvalue =$datasource[$j][1];
$scaend = $j+1;#记录处理下个染色体的开始行
}else
{
last;
}
}
}
print "\n当前染色体最大位点:$maxvalue ||当前染色体开始行:$scastart 下个染色体的开始行:$scaend\n"; #
if(@onesca)
{
for(my $baseid = 0; $baseid<$maxvalue+1; $baseid=$baseid+500)
{
pickline($baseid);
}
}
$scastart = $scaend;
print "\n =======第 $k 个染色体处理结束========\n"; #
}
sub pickline
{
my $baseid=shift;
print ("当前染色体数组:@onesca\n");
my @part500 = grep $_<$baseid+500, @onesca;
print ("500区间数组:@part500\n");
my $myneed = int(rand(500)) + $baseid; #$myneed是一个0和500之间的整数
my @diff= map{abs($_ - $myneed)} @part500;
my $near = &min(@diff); #差值最小,最靠近随机数
print "随机数->最小差值: $myneed -> $near\n";
for(my $m=$scastart;$m<$scaend;$m++)
{
my $posvalue = $datasource[$m][1];
if(abs($posvalue-$myneed) == $near)
{
print "需要的行:".$datasource[$m][0].",$posvalue\n\n";
}
}
#print "删除染色体数组中已处理的部分;
while(@onesca and ($onesca[0] < ($baseid+500)))
{
shift @onesca; #删除
}
}
exit;
复制代码
作者:
niuguohao
时间:
2018-12-25 21:55
回复
4#
hztj2005
谢谢您!我现在还没有完全看明白,稍后继续向您请教!非常感谢~!
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2