Extraire des donnees de deux tableaux

Extraire des donnees de deux tableaux - Perl - Programmation

Marsh Posté le 09-01-2013 à 09:55:38    

Bonjour,
 
Je viens juste de commencer Perl et j'aurai besoin de votre aide.
J'ai 2 tableaux, l'un avec une colonne contenant une liste de genes de la forme: FBgn0025
                                                                                                           FBgn0036
                                                                                                           FBgn0059
                                                                                                           ............
Dans mon deuxieme tableau, j'ai aussi une colonne avec une liste de genes dont certains sont les meme que ceux du tableau precedent et dans une deuxieme colonne, j'ai des informations sur chaque gene.
Ce tableau 2 est de cette forme: FBgn0045  Info
                                          FBgn0036  Info
                                          FBgn0089  Info
                                          ............   ....
Ce que je voudrais, c'est recuperer les infos du tableau 2 mais seulement pour les genes du tableau 1.
en gros je voudrais en fichiers de sortie, un tableaux avec ma liste de genes du tableau 1 et les infos sur ces genes.
 
J'ai essaye different script sans jamais arrive a un resultat.
Voila le dernier script que j'ai fait:
 
use v5.10.1;  
 
open FILEIN, "< tableaux2.txt" or die "Input file open failed: $!";
 
while(defined($l=<FILEIN> )){  
  chomp $l;  
  @a = split /\t/,$l;  
  $transtogene{$a[0]} = $a[1];  
}
close FILEIN;  
 
 
open FILEIN, "< tableaux1.txt" or die "Input file open failed: $!";
 
while(defined($l=<FILEIN> )){  
  chomp $l;  
  ($FBg,$count) = split /\t/,$l;  
  $FBgn = $transtogene{$FBg};  
  $genecount{$FBgn} += $count;  
}
close FILEIN;    
 
 
open FILEOUT, "> tableaux3.txt" or die "Output file open failed: $!";
@k = keys %genecount;  
@k = sort @k;  
foreach $e (@k){
  say FILEOUT "$e\t$genecount{$e}";
}
close FILEOUT;

 
Toute aide ou suggestions me serait utile.  
Merci.

Reply

Marsh Posté le 09-01-2013 à 09:55:38   

Reply

Marsh Posté le 09-01-2013 à 14:27:23    

Bonjour, c'est tout bête, et vous y étiez presque à mon avis:
Vous créez un hash, qui va avoir pour clé le nom ('FBgn0025' par exemple) et pour valeur l'info.
Vous lisez le premier fichier et créez une entrée dans le hash pour chaque ligne avec une valeur bidon pour l'info ('' par exemple)
Vous lisez le second fichier, et pour chaque ligne si le hash a une entrée pour la clé (tester avec exists) vous associez a cette entrée l'info comme valeur.
 
Si ces infos ne vous suffisent pas, je vous écrirais le code, mais à vue de nez ce serait, en partant de votre code (qui manifestement fait d'autres choses)
 
open FILEIN, "< tableaux1.txt" or die "Input file open failed: $!";  
 
while(defined($l=<FILEIN> )){  
  chomp $l;  
  ($FBg, $count) = split /\t/,$l;  
  $transtogene{$FBg} = '';  
}  
close FILEIN;    
 
open FILEIN, "< tableaux2.txt" or die "Input file open failed: $!";  
 
while(defined($l=<FILEIN> )){  
  chomp $l;  
  @a = split /\t/,$l;  
  $transtogene{$a[0]} = $a[1] if exists $transtogene{$a[0]};  
}  
close FILEIN;    
 
open FILEOUT, "> tableaux3.txt" or die "Output file open failed: $!";  
@k = keys %transtogene;  
@k = sort @k;  
foreach $e (@k){  
  say FILEOUT "$e\t$transtogene{$e}";  
}  
close FILEOUT;  
 
A+,


Message édité par gilou le 09-01-2013 à 14:44:32

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 09-01-2013 à 15:32:44    

Merci beucoup pour les infos.
Le code marche tres bien.

Reply

Marsh Posté le 09-01-2013 à 15:48:00    

Chouette!  
Attention au cas des gènes présents dans le premier et pas le second, que j'ai vu en faisant un petit test (je ne connais pas vos données, donc ce n'est peut être pas possible avec).  
Si j'avais eu à l'écrire, j'aurais écrit ceci:
 

Code :
  1. #!/usr/bin/perl
  2. use v5.10.1;
  3. # code propre
  4. use strict;
  5. use warnings;
  6. use autodie;
  7.  
  8. my ($input1, $input2, $output) = ('tg1.txt', 'tg2.txt', 'tg3.txt');
  9. my $fh;
  10. my %data;
  11. # lecture du premier fichier et recupération des infos
  12. open $fh, "< $input1";
  13. foreach (<$fh> ) {
  14.  chomp;
  15.  undef $data{(split(/\t/, $_))[0]} if (/\t/);
  16. }
  17. close $fh;
  18. # lecture du second fichier et recupération des infos
  19. # pour les entrées présentes dans le premier
  20. open $fh, "< $input2";
  21. foreach (<$fh> ) {
  22.  chomp;
  23.  if (/\t/) {
  24.    my ($key, $val) = (split(/\t/, $_))[0,1];
  25.    $data{$key} = $val if exists $data{$key};
  26.  }
  27. }
  28. close $fh;
  29. #suppression des entrées présentes dans le premier seulement
  30. foreach (keys %data) {
  31.  delete $data{$_} unless defined $data{$_};
  32. }
  33. # écriture du fichier de sortie
  34. open $fh, "> $output";
  35. foreach (sort(keys %data)) {
  36.  say $fh "$_\t$data{$_}";
  37. }
  38. close $fh;


En lecture, plutôt que regarder si les lignes sont defined (je comprends d'ailleurs pas trop l'emploi du test avec defined dans votre code), je ne fais une action que si un \t est repéré dans la ligne, ça m'a paru plus efficace au vu de vos lignes utiles.
undef $data{'key'} est un idiome qui force la création de la clé 'key' pour pouvoir mettre sa valeur associée à undef, ce qu'on peut tester ensuite avec defined.
A+,


Message édité par gilou le 09-01-2013 à 16:22:50

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 11-01-2013 à 17:11:53    

Merci encore pour la derniere fois.
 
Helas, j'ai encore un probleme.
J'ai toujours 2 tableaux (2 fichiers excels), mais cette fois je cherche les genes se situant entre deux coordonnees.
Voila a quoi ressemble mon premier tableau:   Start    End      Middle
                                                             1000    1200     1100  
                                                             2200    3000     2600
                                                             5000    6000     5000
 
Et voila a quoi ressemble le deuxieme tableau:   Start    End      Genes
                                                               980      1100      FBgn00026  
                                                               2500    5000      FBgn0027
                                                               3060    4500      FBgn0028
                                                               5200    7000      FBgn0029
                                                               5400    5800      FBgn0030
                                                               6050    8000      FBgn00036
 
En gros je voudrais un fichier de sortie avec seulement les genes et leur coordonnee correspondant seulement aux coordonnees du tableau 1. Ou autrement, les genes se situant sur les coordonnees de mon tableau 1.
C'est a dire si je reprend mon exemple:            Start    End      Genes
                                                               980      1100      FBgn00026  
                                                               2500    5000      FBgn0027
                                                               
                                                               5200    7000      FBgn0029
                                                               5400    5800      FBgn0030
 
J'avoue que je n'arrive pas a faire de script Perl pour faire cela.  
Si quelqu'un avait une solution, cela m'aiderai beaucoup.
Merci d'avance.
                                                             

Reply

Marsh Posté le 11-01-2013 à 21:11:28    

Bonjour,
Je crains de ne pas bien avoir compris sur quel critères vous éliminez la ligne contenant FBgn0029.
Pourriez vous préciser ceci. Merci.
 
Parce que à la base, le code final va probablement ressembler à ceci:

Code :
  1. #!/usr/bin/perl
  2. use v5.10.1;
  3. # code propre
  4. use strict;
  5. use warnings;
  6. use autodie;
  7.  
  8. use Data::Dumper;
  9.  
  10. my ($input1, $input2, $output) = ('gt1.txt', 'gt2.txt', 'gt3.txt');
  11. my ($fh1, $fh2);
  12. my @ranges;
  13.  
  14. open $fh1, "< $input1";
  15. while (<$fh1> ) {
  16.  next if $. == 1; # On saute la ligne de titre
  17.  push @ranges, [(split(/\t/, $_))[0,1]];
  18. }
  19. close($fh1);
  20.  
  21. open $fh1, "< $input2";
  22. open $fh2, "> $output";
  23. while (<$fh1> ) {
  24.  next if $. == 1; # On saute la ligne de titre
  25.  my ($start, $end) = (split(/\t/, $_))[0,1];
  26.  foreach my $range (@ranges) {
  27.    if ( ## un certain critere ## ) {
  28.      print $fh2 $_;
  29.      last;
  30.    }
  31.  }
  32. }
  33. close($fh2);
  34. close($fh1);


Les numéros de colonnes sont 0 et 1, car j'ai testé avec les fichiers d'exemple suivants:

Start End Middle  
1000 1200 1100
2200 3000 2600
5000 6000 5000


et

Start End Genes  
980 1100 FBgn00026  
2500 5000 FBgn0027
3060 4500 FBgn0028
5200 7000 FBgn0029
5400 5800 FBgn0030
6050 8000 FBgn00036


A+,


Message édité par gilou le 12-01-2013 à 13:53:22

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 12-01-2013 à 11:13:10    

Merci pour la reponse.
Alors je n'élimine pas FBgn0029 mais FBgn0028 car ce gene ne recouvre aucune region de mon tableau 1. C'est justement ce que je voudrais, c'est à dire garder seulement les gènes qui recouvre mes regions d'interets du tableau.  
Mon probleme est justement que je n'arrive pas a trouve quels criteres peut me permettre de faire ça.
J'espere que c'est plus claire.
A+,

Reply

Marsh Posté le 12-01-2013 à 13:52:58    

Ah! J'ai pigé!
Le critère devrait être
($range->[0] <= $start and $start <= $range->[1]) or ($range->[0] <= $end and $end <= $range->[1])
C'est a dire que le début pour un gène est dans une zone qui vous intéresse, ou bien que sa fin l'est.
 
Au final ça fait ceci:

Code :
  1. #!/usr/bin/perl
  2. use v5.10.1;
  3. # code propre
  4. use strict;
  5. use warnings;
  6. use autodie;
  7.  
  8. use Data::Dumper;
  9.  
  10. my ($input1, $input2, $output) = ('gt1.txt', 'gt2.txt', 'gt3.txt');
  11. my ($fh1, $fh2);
  12. my @ranges;
  13.  
  14. open $fh1, "< $input1";
  15. while (<$fh1> ) {
  16.  next if $. == 1; # On saute la ligne de titre
  17.  push @ranges, [(split(/\t/, $_))[0,1]];
  18. }
  19. close($fh1);
  20.  
  21. open $fh1, "< $input2";
  22. open $fh2, "> $output";
  23. while (<$fh1> ) {
  24.  next if $. == 1; # On saute la ligne de titre
  25.  my ($start, $end) = (split(/\t/, $_))[0,1];
  26.  foreach my $range (@ranges) {
  27.    if (($range->[0] <= $start and $start <= $range->[1]) or ($range->[0] <= $end and $end <= $range->[1])) {
  28.      print $fh2 $_;
  29.      last;
  30.    }
  31.  }
  32. }
  33. close($fh2);
  34. close($fh1);


ce qui sur les données test me donne ceci en sortie:

980 1100 FBgn00026  
2500 5000 FBgn0027
5200 7000 FBgn0029
5400 5800 FBgn0030


Ce qui colle avec ce que vous m'aviez mis en exemple.
A+,


Message édité par gilou le 12-01-2013 à 13:54:41

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 12-01-2013 à 15:20:51    

C'est exactement ça!
Merci, cela m'aide énormément.
A+,

Reply

Marsh Posté le 14-01-2013 à 14:38:14    

Bonjour,
 
Je suis en train d'utiliser le script que vous m'avez donne et je vous en remercie encore.
Mais j'ai remarque que les genes qui sont beaucoup plus grand que mes valeurs ne sont pas pris en compte.
Par exemple, si j'ai dans le tableau 1:  Start    End      Middle
                                                   1000    2000    1500
Le gene:  Start    End     Middle
              800     4000     1000
Ne vas pas etre pris en compte, alors que je le voudrais.
Ne serait-il pas mieux d'utiliser la valeur "Middle" plutot que le Start et le End.
Merci.
A+,

Reply

Marsh Posté le 14-01-2013 à 14:38:14   

Reply

Marsh Posté le 14-01-2013 à 17:41:59    

Bonjour, je vois que mon critère n'était pas le bon en effet.
En fait, le bon critère est d'exclure les gènes vérifiant la proposition opposée: ils n'ont pas d'intersection avec une zone d'intérêt et donc sont avant le début ou après la fin d'une telle zone.
il suffit donc d'exclure les gènes dont la fin est avant le début de la zone d'intérêt ou dont le début est après la fin de la zone d'intérêt, et donc de remplacer la ligne
if (($range->[0] <= $start and $start <= $range->[1]) or ($range->[0] <= $end and $end <= $range->[1])) {
par
unless (($end < $range->[0]) or ($start > $range->[1])) {
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 15-01-2013 à 13:18:43    

Merci.
Maintenant ca marche.
A+,

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed