[awk] agréger des valeurs de plusieurs lignes sur une seule ....
Résolu
Swiss Knight
Messages postés
2257
Statut
Membre
-
Swiss Knight Messages postés 2257 Statut Membre -
Swiss Knight Messages postés 2257 Statut Membre -
Salut,
Je souhaite agréger des valeurs d'un fichier en fonction d'un champ d'identification de groupe. Le fichier final devrait avoir une ligne par groupe et non plus une par enregistrement.
MWE:
Ici il y a deux groupes différents; 982963 and 982954.
Cible souhaitée:
Le champ du groupe est le $4 du fichier foo.
Les valeurs X Y Z de chaque enregistrement qui constitue un groupe doivent être stockées dans la parenthèse "FLW ()"; qui elle sera suivie une seule fois des autres valeurs de chaque enregistrement qui sont les mêmes aussi. L'ordre d'apparition des triplets X Y Z dans la parenthèse doit correspondre à celui des enregistrements du fichier foo; ils doivent se suivre de la même manière qu'ils se suivent dans ce fichier foo.
Merci.
Pour l'instant j'ai ça mais ça ne fonctionne absolument pas :
Je souhaite agréger des valeurs d'un fichier en fonction d'un champ d'identification de groupe. Le fichier final devrait avoir une ligne par groupe et non plus une par enregistrement.
MWE:
$ head -n4 foo
X;Y;OID;ID;OQTE;QTE;OTYPE;TYPE;Z
603.311;800.928;930;982963;0;XTX;49;comment;191.299
603.512;810.700;930;982963;0;XTX;49;comment;191.341
604.815;802.475;930;982963;0;XTX;49;comment;191.393
601.901;858.701;122;982954;0;XTX;50;comment;194.547
601.851;832.317;122;982954;0;XTX;50;comment;193.733
Ici il y a deux groupes différents; 982963 and 982954.
Cible souhaitée:
$ head -n2 bar
CODE;OID;ID;OQTE;QTE;OTYPE;TYPE
"FLW (603.311 800.928 191.299, 603.512 801.700 191.341, 604.815 802.475 191.393)";982963;0;XTX;49;comment
"FLW (601.901 858.701 194.547, 601.851 832.317 193.733)";982954;0;XTX;49;comment
Le champ du groupe est le $4 du fichier foo.
Les valeurs X Y Z de chaque enregistrement qui constitue un groupe doivent être stockées dans la parenthèse "FLW ()"; qui elle sera suivie une seule fois des autres valeurs de chaque enregistrement qui sont les mêmes aussi. L'ordre d'apparition des triplets X Y Z dans la parenthèse doit correspondre à celui des enregistrements du fichier foo; ils doivent se suivre de la même manière qu'ils se suivent dans ce fichier foo.
Merci.
Pour l'instant j'ai ça mais ça ne fonctionne absolument pas :
awk -F ";" 'NR==1 {print "CODE;"$3";"$4";"$5";"$6";"$7";"$8}; NR>1 {a[$4]=a[$4]}END{for(i in a) { print "\"FLW ("$1","$2","$NF")\";"$3";"i""a[i]";"$5";"$6";"$7";"$8 }}' foo
2 réponses
-
hello
$ cat a4.awk
BEGIN {FS=";"; print "CODE;OID;ID;OQTE;QTE;OTYPE;TYPE"}
NR>1 {t[$4]=t[$4] $1 " " $2 " " $9 ", "; t2[$4]=$5 FS $6 FS $7 FS $8}
END {for (n in t){sub(", *$", "", t[n]); print "\"FLW (", t[n] ")\"" FS n FS t2[n]}}
$ awk -f a4.awk foo
CODE;OID;ID;OQTE;QTE;OTYPE;TYPE
"FLW ( 601.901 858.701 194.547, 601.851 832.317 193.733)";982954;0;XTX;50;comment
"FLW ( 603.311 800.928 191.299, 603.512 810.700 191.341, 604.815 802.475 191.393)";982963;0;XTX;49;comment-
Merci ça fonctionne bien, à part que le champ de liaison était finalement le $3 et pas le $4.
Par contre j'ai essayé de récupérer les entêtes directement avec les identifiants de champ mais ça ne marche pas, j'ai que des points virgules à part sur le premier champ spécifié manuellement pour la 1ère ligne du fichier :
$ cat a4.awk
NR==1 {FS=";"; print "CODE;"$3 FS $4 FS $5 FS $6 FS $7 FS $8}
NR>1 {t[$3]=t[$3] $1 " " $2 " " $9 ", "; t2[$3]=$4 FS $5 FS $6 FS $7 FS $8}
END {for (n in t){sub(", *$", "", t[n]); print "\"FLW (", t[n] ")\"" FS n FS t2[n]}}
De plus, je souhaiterais pouvoir ajouter une constante, mettons 0.2 à chaque valeur $NF du fichier initial avant de procéder à ces opérations, est-ce que c'est possible ?
J'ai essayé de remplacer $9 par $9+=0.2 mais ça me met "syntax error" -
-
Yep nickel! J'avais fais ça aussi entre parenthèses :
NR>1 {t[$3]=t[$3] $1 " " $2 " " ($9+0.2) ", "; t2[$3]=$4 FS $5 FS $6 FS $7 FS $8}
entre temps et ça marche.
Par contre il y a de méchants arrondis (ça coupe après la 3ème décimale) !
Pour le 1er point ce n'est pas grave, c'est moi qui ait mal compris l'organisation de base des données, c'est corrigé.
-
-
Bonjour
Le plus simple à mon avis c'est de lire ton fichier ligne par ligne et peupler un ou des dictionnaires :
https://en.wikibooks.org/wiki/An_Awk_Primer/Arrays
... à partir desquels tu réécriras tes agrégats.
Du coup je t'invite à écrire ton code awk dans un fichier et à l'exécuter viaawk -f
.
Si tu n'es pas bloqué sur le langage, personnellement je le ferais plutôt en python.
Bonne chance