从数字列表生成随机对,确保生成的随机对不存在

时间:2012-08-14 00:21:13

标签: perl random hash numbers

鉴于一组基因和现有的基因对,我想生成一对尚未存在的新基因。

基因文件具有以下格式:

123    
134   
23455  
3242  
3423  
...  
...  

基因对文件具有以下格式:

12,345    
134,23455   
23455,343  
3242,464452  
3423,7655  
...  
...  

但是我仍然知道known_interactions和new_pairs之间的一些共同元素。我不确定错误在哪里。

对于论点,
perl generate_random_pairs.pl entrez_genes_file known_interactions_file 250000
我有一个共同的元素15880.250000是告诉我希望程序产生多少个随机对。

#! usr/bin/perl

use strict;
use warnings;

if (@ARGV != 3) {
    die "Usage: generate_random_pairs.pl <entrez_genes> <known_interactions> <number_of_interactions>\n";
}
my ($e_file, $k_file, $interactions) = @ARGV;

open (IN, $e_file) or die "Error!! Cannot open $e_file\n";
open (IN2, $k_file) or die "Error!! Cannot open $k_file\n";

my @e_file = <IN>; s/\s+\z// for @e_file;
my @k_file = <IN2>; s/\s+\z// for @k_file;

my (%known_interactions);

my %entrez_genes;
$entrez_genes{$_}++ foreach @e_file;

foreach my $line (@k_file) {
    my @array = split (/,/, $line);
    $known_interactions{$array[0]} = $array[1];
}
my $count = 0;

foreach my $key1 (keys %entrez_genes) {
    foreach my $key2 (keys %entrez_genes) {
        if ($key1 != $key2) {
            if (exists $known_interactions{$key1} && ($known_interactions{$key1} == $key2)) {next;}
            if (exists $known_interactions{$key2} && ($known_interactions{$key2} == $key1)) {next;}
            if ($key1 < $key2) { print "$key1,$key2\n"; $count++; }
            else { print "$key2,$key1\n"; $count++; }
        }
        if ($count == $interactions) {
            die "$count\n";
        }
    }
}

2 个答案:

答案 0 :(得分:0)

我看到您的代码没有任何问题。我想知道你的数据中是否有一些空格 - 在逗号之后还是在行尾?用例如

提取数字字段会更安全
my @e_file = map /\d+/g, <IN>;

此外,最好将对的两个元素保留为散列键,这样您就可以检查元素是否存在。如果你确保较低的数字始终是第一个,你不需要进行两次查找。

此示例应该适合您。它没有解决您的需求的随机选择部分,但这不在您自己的代码中,并不是您的直接问题

use strict;
use warnings;

@ARGV = qw/ entrez_genes.txt known_interactions.txt 9 /;

if (@ARGV != 3) {
    die "Usage: generate_random_pairs.pl <entrez_genes> <known_interactions> <number_of_interactions>\n";
}

my ($e_file, $k_file, $interactions) = @ARGV;

open my $fh, '<', $e_file or die "Error!! Cannot open $e_file: $!";
my @e_file = sort { $a <=> $b } map /\d+/g, <$fh>;

open $fh, '<', $k_file or die "Error!! Cannot open $k_file: $!";
my %known_interactions;
while (<$fh>) {
  my $pair = join ',', sort { $a <=> $b } /\d+/g;
  $known_interactions{$pair}++;
}

close $fh;

my $count = 0;
PAIR:
for my $i (0 .. $#e_file-1) {
  for my $j ($i+1 .. $#e_file) {
    my $pair = join ',', @e_file[$i, $j];
    unless ($known_interactions{$pair}) {
      print $pair, "\n";
      last PAIR if ++$count >= $interactions;
    }
  }
}

print "\nTotal of $count interactions\n";

答案 1 :(得分:-1)

首先,您不会从已知交互文件中咀嚼(删除换行符)。这意味着给定一个文件:

1111,2222

你将构建这个哈希:

 $known_interactions{1111} = "2222\n";

这可能是你获得重复条目的原因。我的猜测是(不能确定没有你的实际输入文件)这些循环应该可以正常工作:

 map{
    chomp;
    $entrez_genes{$_}++ ;
 }@e_file;

map {
    chomp;
    my @array = sort(split (/,/));
    $known_interactions{$array[0]} = $array[1];
}@k_file;

另外,作为一般规则,如果我对交互对(生物信息学的乐趣:)进行排序,我发现自己的生活会更轻松。这样我知道111,222和222,111将以相同的方式处理,我可以避免在代码中使用多个if语句。

然后你的下一个循环(恕我直言更易读):

my @genes=keys(%entrez_genes);
for (my $i=0; $i<=$#genes;$i++) {
   for (my $k=$n; $k<=$#genes;$k++) {
     next if $genes[$n] == $genes[$k];
     my @pp=sort($genes[$n],$genes[$k]);
     next unless exists $known_interactions{$pp[0]};
     next if $known_interactions{$pp[0]} == $pp[1];
     print "$pp[0], $pp[1]\n";
     $count++;
     die "$count\n" if $count == $interactions;
  }
}
相关问题