IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

somme de colonne


Sujet :

Langage Perl

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Août 2007
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 142
    Points : 57
    Points
    57
    Par défaut somme de colonne
    Bonjour,

    J'ai un tableau ne contenant que des 1 et 0. Il est possible d'avoir 2 fois le même éléments. Dans ce cas, je souhaiterai n'avoir l'élément qu'une seule fois et faire la somme de chaque colonne et remplacer quand la somme de la colonne est égale à 2 le résultat par 1. Mon souci est dans le calcul de la somme de chaque colonne.
    Si vous pouvez m'aider merci

    gene1 1 0 1
    gene2 0 1 1
    gene3 1 1 0
    gene1 0 0 1

    intermédiare
    gene1 1 0 2
    gene2 0 1 1
    gene3 1 1 0
    gene1 0 0 1

    final
    gene1 1 0 1
    gene2 0 1 1
    gene3 1 1 0
    Voiçi mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    open my $fh, '<', $fichier or die "Impossible de lire le fichier $fichier\n";
     
    my %data;
    my $i=0;
    my $j=0;
     
     
    while(my $ligne = <$fh>){
    	$i++;
    	chomp $ligne;
    	if($ligne =~ /gene.*/){
    		$j++;
    		my ($gene,$champ1,$champ2,$champ3) = split "\t", $ligne;
    		my $element =$champ1."\t".$champ2."\t".$champ3;
    		push @{$data{$gene}}, [$element];
     
    	}
     
    }
     
    for my $id (keys %data) {
    	my @array = @{$data{$id}};
    	$data{$id} = \@array;
    }
    print Dumper \%data;
     
     
    for my $id (keys %data) {
    	print "--$id\n";	
    	my @array = @{$data{$id}};
    	for my $pair (@array) {		
    		print ("\tstart : $pair->[0]\n");
     
     
    		#faire la somme de chaque colonne et quand la somme de la colonne est égale à 2 mettre 1
    		my @hit = split("\t",$pair->[0]);
    	}
    }
     
    close($fh);

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Août 2007
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 142
    Points : 57
    Points
    57
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    open my $fh, '<', $fichier or die "Impossible de lire le fichier $fichier\n";
     
    my %data;
    my $i=0;
    my $j=0;
     
     
    while(my $ligne = <$fh>){
    	$i++;
    	chomp $ligne;
    	if($ligne =~ /gene.*/){
    		$j++;
    		my ($gene,$champ1,$champ2,$champ3) = split "\t", $ligne;
    		my $element =$champ1."\t".$champ2."\t".$champ3;
    		push @{$data{$gene}}, [$element];
     
    	}
     
    }
     
    for my $id (keys %data) {
    	my @array = @{$data{$id}};
    	$data{$id} = \@array;
    }
    print Dumper \%data;
     
     
    for my $id (keys %data) {
    	print "--$id\n";	
            my @tableau=();
    	my @array = @{$data{$id}};
    	for my $pair (@array) {		
    		#print ("\tstart : $pair->[0]\n");
     
    		#faire la somme de chaque colonne et quand la somme de la colonne est égale à 2 mettre 1
    		my @hit = split("\t",$pair->[0]);
                    for (my $m = 0; $m < @hit ; $m++) {
    			print "colonne $m - valeur $hit[$m] \n";
                            $tableau[$m]=$hit[$m];
                            $tableau[$m]=$hit[$m];
                            $tableau[$m]=$hit[$m];
     
     
    		}
    	}
    }
     
    close($fh);
    J'obtiens ceci, mais je bloque pour bloquer sur chaque colonne !
    --gene1
    colonne 0 - valeur 1
    colonne 1 - valeur 1
    colonne 2 - valeur 0
    --gene2
    colonne 0 - valeur 0
    colonne 1 - valeur 1
    colonne 2 - valeur 1
    --gene1
    colonne 0 - valeur 1
    colonne 1 - valeur 0
    colonne 2 - valeur 1
    colonne 0 - valeur 0
    colonne 1 - valeur 0
    colonne 2 - valeur 1

  3. #3
    Membre actif Avatar de olivier1969
    Homme Profil pro
    Assistant aux utilisateurs
    Inscrit en
    Novembre 2013
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Assistant aux utilisateurs
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Novembre 2013
    Messages : 151
    Points : 208
    Points
    208
    Par défaut
    Hello ,

    Un truc comme ça ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    @fh = ('gene1 1 0 1',
           'gene2 0 1 1',
           'gene3 1 1 0',
           'gene1 0 0 1') ;
     
     
    sub maxi {
           ($ch1, $ch2) = @_ ;
           if ( $ch1 > $ch2 ) {
                  return $ch1;
           }
           else {
                  return $ch2;
           }
    }
     
     
    %data = () ;
    foreach (@fh) {
           if($_ =~ /gene.*/){
               ($gene,$champ1,$champ2,$champ3) = split /\s+|\t+/, $_;
               print"$gene,$champ1,$champ2,$champ3" . "\n";
               if (exists($data{$gene})) {
                      ($ch1,$ch2,$ch3) = split /,/, $data{$gene}  ;
                      $data{$gene} = join( ',' , ( maxi($ch1,$champ1), maxi($ch2,$champ2), maxi($ch3,$champ3)) ) ;
                }
                else {
                      $data{$gene} =  join( ',', ($champ1,$champ2,$champ3 ));
               }
           }
    }

  4. #4
    Membre habitué
    Homme Profil pro
    Master Data Manager
    Inscrit en
    Février 2017
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Master Data Manager
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2017
    Messages : 113
    Points : 148
    Points
    148
    Par défaut
    Bonjour.

    Ou encore un truc comme ça:

    Code perl : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
     
    use Modern::Perl;
    use Data::Printer;
     
    my $DEBUG = 0;
     
    # data modele
    my @t = (
      'gene1 1 0 1',
      'gene2 0 1 1',
      'gene3 1 1 0',
      'gene1 0 0 1',
      'gene1 1 0 1',
      'gene2 0 1 1',
      'gene3 1 1 0',
      'gene4 0 0 1',
    );
    say 'Data input:';
    p @t;
     
    # réorganisation des data
    # clef_gene => [[]]
    my $lst_data;
    foreach my $i (@t) {
      my ($entt, @l) = split / /, $i;
      push $lst_data->{$entt}->@*, \@l;
    }
    p $lst_data if $DEBUG;
     
    # traitement
    my $res;
    foreach my $i (keys $lst_data->%*) # pour chaque clef gene*
    { 
        # test nombre d'occurence  
        if ( scalar($lst_data->{$i}->@*) == 1 ) 
        {
          push $res->@*, $i.' '.join( ' ', $lst_data->{$i}->[0]->@*);
        }
        else
        {
          my $t = merge_tab($lst_data->{$i}->[0], $lst_data->{$i}->[1]);
     
          # cas ou plus d'un doublon
          if ( scalar($lst_data->{$i}->@*) > 2 ) {
            foreach my $j ( 2..(scalar($lst_data->{$i}->@*)-1)) {
              $t = merge_tab($t, $lst_data->{$i}->[$j]);
            }
          }
     
          # ajoute la ligne de gene
          push $res->@*, $i.' '.join( ' ', $t->@*);
        }
    }
    say "\nData output: ";
    p $res->@*;
     
    # fusion de 2 tableaux 
    # my $ref_ary = merge_tab( \@tab1, \@tab2 );
    sub merge_tab
    {
        my $t1 = shift;
        my $t2 = shift;
        my $t3;
        foreach my $i (0..(scalar($t1->@*)-1)) {
            push $t3->@*, ($t1->[$i] + $t2->[$i]) >= 1 ? 1 : 0; 
        }
        $t3;
    }

    Sortie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    Data input:
    [
        [0] "gene1 1 0 1",
        [1] "gene2 0 1 1",
        [2] "gene3 1 1 0",
        [3] "gene1 0 0 1",
        [4] "gene1 1 0 1",
        [5] "gene2 0 1 1",
        [6] "gene3 1 1 0",
        [7] "gene4 0 0 1"
    ]
     
    Data output: 
    [
        [0] "gene2 0 1 1",
        [1] "gene3 1 1 0",
        [2] "gene1 1 0 1",
        [3] "gene4 0 0 1"
    ]

  5. #5
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    À peu près la même idée qu'olivier1969, mais en utilisant l'opérateur sur les bits | (OR) à la place de la fonction maxi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    use strict;
    use warnings;
     
    my $fichier = 'gene.txt';
     
    open my $fh, '<', $fichier
        or die "impossible de lire le fichier $fichier\n";
     
    my @order;  # pour garder le même ordre
    my %records; # pour stocker les valeurs
     
    while (<$fh>) {
        chomp;
        my ($key, @values) = split;
     
        if ( exists $records{$key} ) {
            $records{$key}[$_] |= $values[$_] for (0 .. $#values);
            next;
        }
     
        push @order, $key;
        $records{$key} = \@values;
    }
     
    print join(" ", $_, @{$records{$_}}), "\n" for @order;
    (Le script est indépendant du nombre de colonnes)
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  6. #6
    Membre habitué
    Homme Profil pro
    Master Data Manager
    Inscrit en
    Février 2017
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Master Data Manager
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2017
    Messages : 113
    Points : 148
    Points
    148
    Par défaut
    Très bonne idée d'utiliser l'opérateur '|'. Cette solution semble la plus adapté à la description du problème.

Discussions similaires

  1. Somme de colonne comme sur Sql Server
    Par Soulama dans le forum Requêtes et SQL.
    Réponses: 8
    Dernier message: 16/06/2010, 13h51
  2. Somme de Colonne quickreport
    Par khier dans le forum Bases de données
    Réponses: 1
    Dernier message: 20/01/2007, 13h44
  3. somme de colonnes HTML
    Par freestyler1982 dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 09/11/2006, 11h27
  4. faire une somme de colonnes ?
    Par viny dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 08/09/2006, 15h49
  5. Réponses: 5
    Dernier message: 07/06/2006, 17h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo