2010-08-18 5 views
1

Donc mon échantillon de données est dans le format suivant.Besoin de comparer les valeurs dans un fichier où la première colonne se répète

jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 18150 18354 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 19856 19974 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 21455 21638 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 21727 21897 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 21980 22063 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 24670 24811 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 34741 34902 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 3649 3836 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 59253 59409 
jgi|Xentr4|100173|gw1.779.90.1 scaffold_779 101746 101969 
jgi|Xentr4|100173|gw1.779.90.1 scaffold_779 106436 107233 

et ce que je tente de faire est pour chaque nom unique dans la première colonne, récupérer la valeur min pour la colonne 3 et la valeur maximale de la colonne 4. Ainsi, l'entrée finale aura le même, un fichier délimité par des tabulations, sauf qu'il aura les deux premières colonnes pour chaque nom unique, alors les troisième et quatrième colonnes seront les valeurs min et max mentionnées ci-dessus. Je suis assez novice en programmation et j'ai essayé de le faire en utilisant des hachages mais j'ai lamentablement échoué. J'essaie maintenant avec des tableaux/expressions régulières comme vu ci-dessous.

open (IN, "POS2") || die "nope\n"; 
my $prev_qn = super; 
my $prev_sn = ultra; 
my $prev_start = non; 
my $prev_end = nono; 
while (<IN>) { 
    chomp; 
    push (@list, "$_"); 
} 
close (IN); 
foreach $v (@list) { 
    $info = $v; 
    ($query_name, $scaf_num, $start, $end) = split(/\t/, $info); 
    unless ($info =~ m/^$prev_qn/) { 
     push @ready, $info; 
     $prev_qn = $query_name; 
     $prev_sn = $scaf_num; 
     $prev_start = $start; 
     $prev_end = $end; 
    } 
    else { 
     if ($start < $prev_start) { 
      splice(@ready,2,1,$start); 
     } 
     if ($end > $prev_end) { 
      splice(@ready,3,1,$end); 
     } 
     $prev_qn = $query_name; 
     $prev_sn = $scaf_num; 
     $prev_start = $start; 
     $prev_end = $end; 
    } 

    foreach $z (@ready) { 
     print "$z\n"; 
    } 
} 

la sortie que cela renvoie est ci-dessous.

jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 18150 18354 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 18150 18354 
19974 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 18150 18354 
19974 
21638 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 18150 18354 
19974 
21638 
21897 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 18150 18354 
19974 
21638 
22063 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 18150 18354 
19974 
21638 
24811 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 18150 18354 
19974 
21638 
34902 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 18150 18354 
19974 
3649 
34902 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 18150 18354 
19974 
3649 
59409 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 18150 18354 
19974 
3649 
101969 

Il semble donc clair que le fichier est en train de faire la comparaison bien, mais il ne remplace pas les éléments du tableau comme prévu, les annexant simplement en dessous et en remplaçant ceux-ci. De plus, il ne s'imprime jamais après le premier nom unique. Aucune suggestion?

Répondre

0

Est-ce que c'est ce que vous cherchez?

open (IN, "POS2") || die "nope\n"; 
my %data; 

# Read data line by line 
while (<IN>) 
{ 
    chomp; 
    my @fields = split /\t/; 

    # Note $fields[0] is the name by which we want to group. 
    if (defined $data{$fields[0]}) 
    { 
     # If there is already an entry for this name, update it 
     $data{$fields[0]} = [ 
      $fields[1], 
      $data{$fields[0]}[1] < $fields[2] ? $data{$fields[0]}[1] : $fields[2], 
      $data{$fields[0]}[2] > $fields[3] ? $data{$fields[0]}[2] : $fields[3] 
     ]; 
    } 
    else 
    { 
     # Otherwise, create a new one 
     $data{$fields[0]} = [ $fields[1], $fields[2], $fields[3] ]; 
    } 
} 
close (IN); 

# Output one row for each group 
foreach my $name (keys %data) 
{ 
    my ($stuff, $min, $max) = @{$data{$name}}; 
    print "$name\t$stuff\t$min\t$max\n"; 
} 

J'ai essayé et sorties ceci:

jgi|Xentr4|100173|gw1.779.90.1 scaffold_779 101746 107233 
jgi|Xentr4|100164|gw1.1441.2.1 scaffold_1441 3649 59409 

Est-ce ce que vous vouliez?

+0

deux de ceux travaillé pour moi, merci les gars tellement, j'avais essayé la stratégie de hachage avant, mais était en train de s'enliser dans la syntaxe, de sorte que ces scripts vont également m'aider à apprendre à mieux mettre les choses en place – Adam

1

Voici une façon de le faire. Fournissez simplement le nom du fichier d'entrée en tant qu'argument de ligne de commande. L'opérateur <> ouvrira le fichier et fournira les lignes à votre script.

use strict; 
use warnings; 

my %h; 

while (my $line = <>){ 
    chomp $line; 
    my ($k, $scaff, $mn, $mx) = split /\t/, $line; 

    $h{$k} = { min => 9e99, max => -9e99 } unless exists $h{$k}; 

    $h{$k}{min} = $mn if $mn < $h{$k}{min}; 
    $h{$k}{max} = $mx if $mx > $h{$k}{max}; 
} 

for my $k (sort keys %h){ 
    print join("\t", $k, $h{$k}{min}, $h{$k}{max}), "\n"; 
} 

J'utilise un hachage de-hash pour stocker les informations min et max, car il rend le code plus déclarative et parce qu'il est flexible. Par exemple, supposons que vous décidez que la sortie doit conserver l'ordre de la première apparition de n'importe quel nom de la colonne 1. Ajoutez simplement un autre élément à la structure de hachage de hachage pour suivre le numéro de ligne d'entrée chaque fois qu'un nom apparaît:

$h{$k} = { min => 9e99, max => -9e99, line_n => $. } unless exists $h{$k}; 

ensuite utiliser ce nouveau morceau de l'info lors du tri de la sortie:

for my $k (sort { $h{$a}{line_n} <=> $h{$b}{line_n} } keys %h){ 
    # Same as above. 
} 
0

peut effectuer les opérations suivantes:

use FileHandle; 

$file = new FileHandle "input_file"; 
@array = <$file>; 
close $file; 

%seen =(); 

foreach (@array){ 
    ($col1,$col2,$col3,$col4) = split(/[\t\s]+/,$_); 
    push(@newarray,$_) unless $seen{$col1}++; 
} 
print @newarray; 
Questions connexes