Optimiser PROC TTEST sur des milliers de variables et structurer ses données
Simon 12 vues
Niveau de difficulté
Confirmé
Publié le :
Le conseil de l'expert
Stéphanie
Le réflexe de la boucle macro est souvent l'ennemi de la performance : lancer 2 500 fois une procédure est incroyablement coûteux pour le système. La règle d'or en statistique SAS est de privilégier la structure des données (format "Long") pour exploiter le traitement par groupe (BY statement). C'est la différence entre un code qui tourne en 30 minutes et un code qui tourne en 30 secondes
L'analyse de données d'expression génétique présente souvent un défi de taille : la multiplicité des variables. Lorsqu'il s'agit de comparer l'expression de milliers de gènes entre deux groupes (par exemple, des sujets "affectés" vs "non affectés"), l'approche naïve consiste souvent à utiliser des macros pour boucler sur chaque variable.
Cependant, cette méthode peut se heurter à des problèmes de performance et, plus sournoisement, à des erreurs de structure de données menant à des résultats nuls ($n=0$).
Le piège de l'instruction PAIRED et des données manquantes
Imaginez un jeu de données où chaque ligne représente un sujet. Vous avez des colonnes pour les gènes d'individus sains (unaffected_gene_x) et d'autres pour les individus malades (affected_gene_x).
Si vous tentez d'utiliser l'instruction PAIRED dans PROC TTEST :
La Solution : Restructurer les données ("Wide to Long")
Au lieu de créer une macro complexe qui lance PROC TTEST 2500 fois (ce qui est inefficace), la meilleure pratique consiste à restructurer les données pour n'avoir qu'une seule colonne de valeurs et une colonne d'identification (Groupe/Statut).
Voici comment transformer vos données "larges" en données "longues" avec une étape DATA et des tableaux (ARRAY) :
data analyse_genes;
set donnees_source;
/* Déclaration des tableaux pour vos colonnes existantes */
/* Ajustez la dimension (ici 10) au nombre réel de gènes (ex: 2500) */
array u unaffected_gene_1 - unaffected_gene_10;
array a affected_gene_1 - affected_gene_10;
/* Boucle pour pivoter les données */
do gene_id = 1 to dim(u);
/* Traitement du cas 'Non Affecté' */
if u[gene_id] ne . then do;
status = 'Unaffected';
value = u[gene_id];
output;
end;
/* Traitement du cas 'Affecté' */
if a[gene_id] ne . then do;
status = 'Affected';
value = a[gene_id];
output;
end;
end;
keep gene_id status value;
run;
/* Tri indispensable pour le traitement par groupe */
proc sort data=analyse_genes;
by gene_id;
run;
1
DATA analyse_genes;
2
SET donnees_source;
3
/* Déclaration des tableaux pour vos colonnes existantes */
4
/* Ajustez la dimension (ici 10) au nombre réel de gènes (ex: 2500) */
5
array u unaffected_gene_1 - unaffected_gene_10;
6
array a affected_gene_1 - affected_gene_10;
7
8
/* Boucle pour pivoter les données */
9
DO gene_id = 1 to dim(u);
10
/* Traitement du cas 'Non Affecté' */
11
IF u[gene_id] ne . THENDO;
12
STATUS = 'Unaffected';
13
value = u[gene_id];
14
OUTPUT;
15
END;
16
17
/* Traitement du cas 'Affecté' */
18
IF a[gene_id] ne . THENDO;
19
STATUS = 'Affected';
20
value = a[gene_id];
21
OUTPUT;
22
END;
23
END;
24
keep gene_id STATUS value;
25
RUN;
26
27
/* Tri indispensable pour le traitement par groupe */
28
PROC SORTDATA=analyse_genes;
29
BY gene_id;
30
RUN;
Cette transformation permet de passer d'une structure dispersée à une structure optimisée pour l'analyse statistique de groupe.
Exécuter le T-Test efficacement
Une fois les données restructurées, plus besoin de macro. Une seule procédure PROC TTEST suffit, en utilisant l'instruction BY pour traiter chaque gène séparément et CLASS pour définir les groupes.
proc ttest data=analyse_genes;
by gene_id; /* Effectue le test pour chaque gène */
class status; /* Définit les groupes (Affected / Unaffected) */
var value; /* La variable contenant la mesure */
run;
1
PROC TTESTDATA=analyse_genes;
2
BY gene_id; /* Effectue le test pour chaque gène */
3
class STATUS; /* Définit les groupes (Affected / Unaffected) */
4
var value; /* La variable contenant la mesure */
5
RUN;
Cette méthode est nettement plus rapide que d'invoquer la procédure des milliers de fois.
Automatiser la récupération des résultats significatifs
Avec des milliers de tests, lire la sortie standard est impossible. L'astuce consiste à utiliser ODS OUTPUT pour récupérer les statistiques (valeurs t et p-values) dans une table, puis de filtrer cette table.
/* Redirection des résultats vers une table SAS */
ods output ttests = resultats_ttests;
proc ttest data=analyse_genes;
by gene_id;
class status;
var value;
run;
/* Filtrer pour ne garder que les différences significatives */
data genes_significatifs;
set resultats_ttests;
/* On filtre souvent sur la méthode Pooled ou Satterthwaite selon l'égalité des variances */
where Probt < 0.05;
run;
1
/* Redirection des résultats vers une table SAS */
2
ods OUTPUT ttests = resultats_ttests;
3
4
PROC TTESTDATA=analyse_genes;
5
BY gene_id;
6
class STATUS;
7
var value;
8
RUN;
9
10
/* Filtrer pour ne garder que les différences significatives */
11
DATA genes_significatifs;
12
SET resultats_ttests;
13
/* On filtre souvent sur la méthode Pooled ou Satterthwaite selon l'égalité des variances */
14
where Probt < 0.05;
15
RUN;
La table resultats_ttests contiendra des variables comme tValue (statistique t) et Probt (la p-value), vous permettant d'identifier immédiatement les gènes d'intérêt parmi des milliers.
Avertissement important
Les codes et exemples fournis sur WeAreCAS.eu sont à but pédagogique. Il est impératif de ne pas les copier-coller aveuglément sur vos environnements de production. La meilleure approche consiste à comprendre la logique avant de l'appliquer. Nous vous recommandons vivement de tester ces scripts dans un environnement de test (Sandbox/Dev). WeAreCAS décline toute responsabilité quant aux éventuels impacts ou pertes de données sur vos systèmes.
SAS et tous les autres noms de produits ou de services de SAS Institute Inc. sont des marques déposées ou des marques de commerce de SAS Institute Inc. aux États-Unis et dans d'autres pays. ® indique un enregistrement aux États-Unis. WeAreCAS est un site communautaire indépendant et n'est pas affilié à SAS Institute Inc.
Ce site utilise des cookies techniques et analytiques pour améliorer votre expérience.
En savoir plus.