Concaténation et fusion de tables

La concaténation de tables : Instruction SET

Il s'agit de "coller verticalement" les observations de deux tables a et b afin de n'obtenir qu'une seule table. C'est encore l'instruction SET qui va servir dans ce cas.

Prenons comme exemple les deux tables a et b suivantes :

table a
nomnote
toto12
titi14
tata18
table b
nomnote
titi10
tutu8

Alors le programme suivant :

DATA ab;
SET a b;
RUN;

Fournit le résultat suivant :

table ab
nomnote
toto12
titi14
tata18
titi10
tutu8

Les colonnes portant le même nom sont regroupées en une seule colonne. Les individus de b sont recopiés à la suite des individus de a, sans souci de classement. Pour remédier à cela, on peut effectuer un "interclassement".

L'interclassement de deux tables : Instructions SET et BY

Il s'agit simplement d'ajouter une instruction BY après l'instruction SET.

DATA ab;
SET a b;
BY nom;
RUN;

Ce programme ne fonctionne que si les deux tables ont auparavant été triées selon la variable nom (ce qui n'est pas le cas ici). Pour trier une table, on utilise une procédure PROC SORT.

Supposant que l'on ait trié les tables, le programme ci-dessus fournit le résultat suivant :

table ab
nomnote
tata18
titi14
titi10
toto12
tutu8

A noter qu'il revient au même de réaliser la concaténation simple sur données non triées puis de trier le résultat (la table ab) à l'aide d'une PROC SORT.

Distinction des données selon leur table d'origine

Supposons maintenant que la note de la table a ait un sens différent de la note de la table b. La simple concaténation des deux tables perd cette information. Deux solutions se présentent à nous :

Créer deux variables « note » différentes :

Il suffit de renommer l'une des deux variables note, comme suit :

DATA ab;
SET a b (rename=(note=note2));
RUN;

Ce programme fournit le résultat suivant :

table ab
nomnotenote2
toto12.
titi14.
tata18.
titi.10
tutu.8

On voit bien dans ce contexte la différence qu'il y a à traiter le changement de nom d'une variable comme option de l'instruction de copie ou comme instruction indépendante.
En effet, le programme suivant :

DATA ab;
SET a b;
RENAME note=note2;
RUN;

Aurait donné le résultat suivant :

table ab
nomnote2
toto12
titi14
tata18
titi10
tutu8

Soit exactement le même résultat qu'avec le tout premier programme, à ceci près que la deuxième colonne ne porte plus le même nom !

Ajouter une colonne type de note :

La méthode précédente présente un inconvénient majeur, celui de générer de nombreuses valeurs manquantes.
La deuxième méthode consiste à ajouter une colonne indiquant la provenance des observations. Pour cela, on utilise l'option IN= de l'instruction SET :

DATA ab;
SET a (in=x) b;
IF x=1 THEN origine="a";
ELSE origine="b";
RUN;

Ce programme fournit le résultat suivant :

table ab
nomnoteorigine
toto12a
titi14a
tata18a
titi10b
tutu8b

La fusion de tables : Instruction MERGE

Mais dans un cas tel que celui-ci, où l'on dispose de différentes données sur un même ensemble d'individus, on pourrait vouloir obtenir une table dont chaque observation corresponde à un individu.
Ici, on souhaiterait avoir la table suivante :

table ab
nomnote_anote_b
tata18.
titi1410
toto12.
tutu.8

Il s'agit en quelque sorte de "coller horizontalement" les deux tables, ce qui en SAS s'appelle une fusion. On utilise alors l'instruction MERGE.
De plus, ici, on "contrôle" la fusion afin de mettre en concordance les données d'un même individu. Ce contrôle s'effectue grâce à une instruction BY.

Le programme permettant d'obtenir le tableau ci-dessus est alors :

DATA ab;
MERGE a (rename=(note=note_a)) b (rename=(note=note_b));
BY nom;
RUN;

Remarque :
Comme chaque fois que l'on utilise une instruction BY, il est nécessaire d'opérer sur des tables déjà triées.

Remarque 2 :
Si l'on oublie de renommer les variables, la variable "note" de la table b vient écraser la variable "note" de la table a, et l'on obtient :

table ab
nomnote
tata18
titi10
toto12
tutu8

Remarque 3 :
Si l'on ne contrôle pas la fusion, on a une simple juxtaposition des tableaux. Dans le cas où les tables ne sont pas triées (et à condition de renommer les variables), cela donne :

table ab
nom_anote_anom_bnote_b
toto12titi10
titi14tutu8
tata18  

La mise à jour d'une table à partir des données d'une autre table : Instruction UPDATE

Supposons maintenant que les notes de la table a correspondent aux notes d'un examen donné et que les notes de la table b soient celles de l'examen de rattrapage correspondant. Les données de b doivent donc venir compléter, voire corriger, les données de a. On utilise alors l'instruction UPDATE.

Le programme suivant :

DATA a_b;
UPDATE a b;
BY nom;
RUN;

Doit bien entendu être appliqué à a et b après tri de ces tables selon le nom.
Il fournit le résultat suivant :

table ab
nomnote
tata18
titi10
toto12
tutu8

Titi ayant passé le rattrapage, sa note provenant de a est écrasée par sa note provenant de b.
Tutu n'avait pas passé l'examen initial. Il est ajouté à la table !

Remarque :
On obtient ici le même résultat qu'en effectuant une fusion contrôlée sur le nom, dans le cas où l'on ne renomme pas les variables « note ». Les deux méthodes ne sont cependant pas équivalentes. Avec UPDATE, seules les valeurs non manquantes écrasent les anciennes valeurs !

Remarques sur l'instruction BY :

On vient de voir plusieurs cas d'utilisation de l'instruction BY. A ce stade, il convient de remarquer qu'il s'agit d'une instruction très courante, que l'on retrouvera aussi dans le cadre d'étapes PROC (voir partie II).
Il est important de comprendre que BY en soi-même n'effectue aucun tri. Si la table issue d'un interclassement, d'une fusion contrôlée ou d'une mise à jour est triée, c'est que les tables en entrée l'étaient ! Le travail de BY consiste à "contrôler" les valeurs de la variable désignée afin de les mettre en concordance. Le but est de repérer les données appartenant à un même individu. Ainsi, une fusion contrôlée ou une mise à jour doit s'effectuer selon une variable qui permet d'identifier l'individu.
Dans l'exemple ci-dessus, on a considéré que le nom pouvait servir d'identifiant. Dans un cas concret, il vaudra mieux éviter (risque d'homonymes).