Dans la gestion de données, la déduplication est une tâche classique. Habituellement, lorsqu'on parle de "supprimer les doublons", on souhaite conserver une ligne unique pour chaque clé et éliminer les répétitions. C'est ce que fait très bien un PROC SORT avec l'option NODUPKEY.
Cependant, il existe un cas de figure plus strict : supprimer intégralement tout groupe de données qui présente des doublons. Si un identifiant apparaît plusieurs fois, on considère que la donnée est "contaminée" ou ambigüe, et on ne veut garder aucune trace de ces enregistrements. Seuls les identifiants réellement uniques (qui n'apparaissent qu'une seule fois dans la table d'origine) doivent survivre.
Prenons l'exemple d'une table contenant un identifiant client (ID) et une année (Year). Une observation est définie par la combinaison ID + Year.
Données en entrée :
| Obs | ID | Year | Var1 | Statut |
| 1 | 1 | 1999 | 5 | Unique (à garder) |
| 2 | 2 | 2000 | 10 | Doublon |
| 3 | 2 | 2000 | 8 | Doublon |
| 4 | 2 | 2000 | 6 | Doublon |
| 5 | 3 | 2001 | 7 | Unique (à garder) |
| 6 | 4 | 2002 | 12 | Doublon |
| 7 | 4 | 2002 | 15 | Doublon |
L'objectif est d'obtenir une table qui ne contient que les observations 1 et 5. Les groupes d'ID 2 et 4 doivent disparaître totalement.
Si vous utilisez PROC SORT NODUPKEY, SAS© conservera la première ligne de chaque groupe (la ligne 2 et la ligne 6 resteraient), ce qui n'est pas le résultat souhaité ici.
La méthode la plus élégante et la plus concise pour réaliser cette opération utilise PROC SQL. L'idée est de grouper les données par la clé d'identification, de compter le nombre d'éléments dans chaque groupe, et de ne filtrer que ceux dont le compte est strictement égal à 1.
Le Code :
Comment ça marche ?
GROUP BY id, year : SAS© regroupe virtuellement les lignes qui partagent le même couple ID/Année.
HAVING count(*) = 1 : C'est la condition de filtrage appliquée après le regroupement.
Pour l'ID 1 (Année 1999), le compte est de 1. -> Gardé.
Pour l'ID 2 (Année 2000), le compte est de 3. -> Rejeté (toutes les lignes du groupe sont ignorées).
Cette approche est très efficace car elle évite des étapes multiples de tri et de marquage (flagging) dans une étape Data classique.
Pour les puristes de l'étape DATA, obtenir le même résultat nécessiterait une logique de "double lecture" ou l'utilisation des variables automatiques first. et last. après un tri, en vérifiant si first.id est égal à last.id (ce qui signifie qu'il n'y a qu'une seule ligne pour cet ID).