[awk] agréger des valeurs de plusieurs lignes sur une seule ....

Résolu/Fermé
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 - Modifié par Swiss Knight le 27/07/2016 à 01:07
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 - 27 juil. 2016 à 14:20
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:

    $ 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
A voir également:

2 réponses

dubcek Messages postés 18755 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 14 novembre 2024 5 621
27 juil. 2016 à 10:23
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
1
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 110
Modifié par Swiss Knight le 27/07/2016 à 13:24
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"
0
dubcek Messages postés 18755 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 14 novembre 2024 5 621
Modifié par dubcek le 27/07/2016 à 13:29
j'ai pas compris les points 1 et 2
pour le 3:
NR>1 {$9+=0.2; t[$4]=t[$4] $1 " " $2 " " $9 ", ";

ou
NR>1 {t[$4]=t[$4] $1 " " $2 " " $9+0.2 ", ";


point 2
BEGIN {FS=";"}
NR==1 {print }
0
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 110
27 juil. 2016 à 14:20
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é.
0
mamiemando Messages postés 33378 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 25 novembre 2024 7 802
27 juil. 2016 à 10:03
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 via
awk -f
.

Si tu n'es pas bloqué sur le langage, personnellement je le ferais plutôt en python.

Bonne chance
0