Les Tests Statistiques en SAS

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 53

Aide SAS

Tests statistiques sous SAS


version 0.9.2
Raphaël Busson (Université de Caen)
[email protected]
21 juillet 2015

Projet de diffusion des savoirs mathématiques : Ln(3)

Raphaël Busson (Université de Caen) GNU General Public License Photographie de Yair Haklai
Aide

Table des matières

1 Tests de normalités 6
1.1 Proc univariate. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2 Tests d’adéquation à une loi 7


2.1 Proc univariate. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

3 Tests de comparaison de deux échantillons différence 8


3.1 Comparaison de moyennes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.2 Test de non-infériorité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.3 Test du χ2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.4 Test du χ2 de Mantel-Haenszel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.5 Test de Wilcoxon (Wilcoxon–Mann–Whitney ou Mann–Whitney) . . . . . . . . . . . . . . . . . . . 9
3.6 Test de Kruskal-Wallis. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.7 Test des médianes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

4 Correction en cas de tests multiples indépendants 11


4.1 Correction de Bonferroni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.2 Correction de Dunn-Šidák . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

5 Tests de comparaison de deux échantillons appariés 12


5.1 Test signé des rangs de Wilcoxon. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

6 Tests de comparaison de K échantillons indépendants 13


6.1 Test ANOVA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
6.2 Test de Kruskal-Wallis. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
6.3 Test de Jonckheere-Terpstra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
6.4 Test de Cochran–Mantel–Haenszel (deux variables croisées) . . . . . . . . . . . . . . . . . . . . . . 14

7 Tests de comparaison de K échantillons indépendants (dispersion) 15


7.1 Test de Fisher (K=2) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
7.2 Test de Bartlett . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
7.3 Test de Cochran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
7.4 Test F-max de Hartley. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
7.5 Test de Levene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
7.6 Test de Brown-Forsythe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
7.7 Test de Klotz. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
7.8 Test de Mood . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Raphaël Busson (Université de Caen) GNU General Public License 3


Aide SAS

8 Test d’association entre variables 18


8.1 Test sur le coefficient de corrélation de Pearson. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
8.2 Test sur le coefficient de corrélation de Spearman . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
8.3 Test sur le coefficient de corrélation Gamma de Goodman-Kruskal . . . . . . . . . . . . . . . . . . 18
8.4 Test sur le coefficient de corrélation Tau-a de Kendall . . . . . . . . . . . . . . . . . . . . . . . . . 18
8.5 Test sur le coefficient de corrélation Tau-b de Kendall . . . . . . . . . . . . . . . . . . . . . . . . . 19
8.6 Test sur le coefficient de corrélation Tau-c de Kendall . . . . . . . . . . . . . . . . . . . . . . . . . 19
8.7 Test sur le coefficient de dépendance de Hoeffding . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
8.8 Test du χ2 de Mantel-Haenszel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
8.9 Coefficient Kappa de Fleiss . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
8.10 Coefficient α de Cronbach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

9 Tests suite à une régression 21


9.1 Recherche la meilleur puissance de la variable expliquée pour l’expliquer . . . . . . . . . . . . . . . 21
9.1.1 Statistique de Box-Cox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
9.1.2 Méthode par création de variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
9.2 Tests de normalité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
9.2.1 Test de symétrie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
9.3 Tests de tolérance et variance inflation factors (VIF) . . . . . . . . . . . . . . . . . . . . . . . . . . 30
9.4 Tests sur la présence d’individus trop influents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
9.4.1 Distance de Cook (meilleur) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
9.4.2 R-Student (très bon) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
9.4.3 DFFITS (très bon) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
9.4.4 Covariance ratio (bon) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
9.5 Tests de stabilité des coefficients (avec distance de Cook) . . . . . . . . . . . . . . . . . . . . . . . 32
9.6 Comparer deux modèles avec un test Anova. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

10 Tests suite à une régression logistique 34


10.1 Comparaison de 2 courbes ROC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
10.1.1 Sur la partie d’apprentissage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
10.1.2 Sur la partie de validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
10.2 Test de Hosmer-Lemeshow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
10.3 Tests de tolérance et variance inflation factors (V IF ) . . . . . . . . . . . . . . . . . . . . . . . . . 36

11 Test comparaison de deux courbes de survies 38


11.1 Log-rank . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
11.2 Log-rank de Peto (le meilleurs) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
11.3 Prentice-Wilcoxon (le plus sensible) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

12 Analyses intermédiaires 41
12.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
12.2 Correction de Pocock (non-recommandé) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
12.3 Correction de O’Brien et Flemming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
12.4 Correction de Lan et Demets (Pocok) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
12.5 Correction de Lan et Demets (O’Brien et Flemming) . . . . . . . . . . . . . . . . . . . . . . . . . . 43
12.6 Correction power family . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
12.7 Correction de Peto - Haybittle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
12.8 Méthode de triangulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

4 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

13 Tests de comparaison de deux échantillons non-homogène avec score de propension 45


13.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
13.2 Par la modification des poids . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
13.3 Par la création de strates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
13.4 Par l’appariement 1 :1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
13.4.1 Macro appariement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
13.4.2 Appariement mahalanobis metric . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
13.4.3 Global optimal algorithmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
13.5 Par l’ajout d’une co-variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

Raphaël Busson (Université de Caen) GNU General Public License 5


Aide

Chapitre 1

Tests de normalités

1.1 Proc univariate


La proc univariate fournie 4 tests non-paramétriques de base :
• Shapiro-Wilk (si l’échantillon n’excède pas 2000)

• Kolmogorov-Smirnov
• Cramer-von Mises
• Anderson-Darling

proc univariate normal data=table;


var variable_testee;
run;

On peut également lui demander un histogramme pour ce faire une idée.

proc univariate normal data=table;


var variable_testee;
histogram variable_testee / normal;
run;

6 Raphaël Busson (Université de Caen) GNU General Public License


Aide

Chapitre 2

Tests d’adéquation à une loi

2.1 Proc univariate


On peut tester l’adéquation aux lois bêta (beta), exponentiel (exponential), gamma (gamma), gumbel
(gumbel), gaussien inverse (igauss), lognormal (lognormal), normal (normal), pareto généralisé (pareto),
puissance (power), Rayleigh (rayleigh), Johnson SB (sb), Johnson SU (su) et weibull (weibull). Il est possible
de mettre l’option est derrière une valeur d’un paramètre, pour que l’adéquation à la distribution avec la
valeur optimal du paramètre soit testée en supplément.

proc univariate normal data=table;


var variable_testee;
histogram / loi(parametre_1=valeur_1 parametre_n=valeur_n);
run;

Raphaël Busson (Université de Caen) GNU General Public License 7


Aide

Chapitre 3

Tests de comparaison de deux échantillons


différence

3.1 Comparaison de moyennes


On effectue un test de Student d’égalité des moyennes. Il faut donc avoir une variable quantitative. Par
défaut, la proc ttest fait également un test d’égalité de la variance. Elle donne les résultats avec supposition
d’égalité et avec supposition d’inégalité de la variance.

proc ttest data=table;


class variable_groupe;
var variable_quantitative_cible;
run;

3.2 Test de non-infériorité


On possède deux critère de jugement (exemple la survie et la qualité de vie). On a montré que d’après notre
deuxième critère il y a une amélioration. On estime que cette amélioration peut compenser une dégradation
du premier critère que l’on fixe à m. On va donc chercher à montrer que notre premier critère de jugement
n’est pas plus mauvais avec une marge m et un risque α.

proc ttest data=table h0=marge sides=L;


class groupe;
var variable_jugement;
run;

/*ou pour une proportion comparait à une proportion de reference*/

proc freq data=table;


table variable_jugement /
binomial(noninferiority
level= "Normal"
p =.91 /*proportion dans la population témoin*/

8 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

margin= .01 /*marge*/


var= null);
run;

3.3 Test du χ2
On dispose de d’une variable qualitative. Je rappelle que pour pouvoir utiliser ce test, il faut que les
effectifs théoriques soient supérieur à 5. Si ce n’est pas le cas, mais que la variable est ordinales, utilisez le
test χ2 de Mantel-Haenszel page 9. Si la variable n’a que deux modalités on peut utilisé le test exacte de
Fisher page 15 (attention ce test est gourmand en calculs).

proc freq data=table;


table groupe*variable / chisq;
run;

A noter que cette commande fournit aussi le test de Student quand il est possible.

3.4 Test du χ2 de Mantel-Haenszel


Il faut que la variable soit quantitative ou qualitatives ordinales. Ce test utilise le coefficient de corrélation
linéaire de Pearson. 'Ce test est dans la plus part des cas mieux adapté que le test de Wilcoxon.' Si la variable
est quantitative continue on pourra privilégier un test du log-rank page 38.

proc freq data=table;


table groupe*variable_quantitative_ou_ordonee / chisq;
run;

3.5 Test de Wilcoxon (Wilcoxon–Mann–Whitney ou Mann–Whitney)


Il faut que la variable soit quantitative ou qualitatives ordinales. 'Ce test est dans la plus part des cas
moins adapté que le test de Mantel-Haenszel page 9.'

proc npar1way data=table wilcoxon;


class echantillons;
var var_quantitative_ou_ordinale;
run;

3.6 Test de Kruskal-Wallis


Il faut que la variable soit quantitative ou qualitatives ordinales. Les test de Wilcoxon (page 9) et de
Mantel-Haenszel (page 9) sont préférable.
Raphaël Busson (Université de Caen) GNU General Public License 9
Aide SAS

proc npar1way data=table wilcoxon;


class echantillons;
var var_quantitative_ou_ordinale;
run;

3.7 Test des médianes


Il faut que la variable soit quantitative. Ce n’est pas un test a privilégier.

proc npar1way data=table median;


class echantillons;
var var_quantitative;
run;

10 Raphaël Busson (Université de Caen) GNU General Public License


Aide

Chapitre 4

Correction en cas de tests multiples indé-


pendants

4.1 Correction de Bonferroni


Vous voulez montrait qu’il existe une différence entre deux échantillon indépendant. Vous décidez faire
k tests indépendants. Votre probabilité de conclure que les deux échantillons augment avec le nombre de
tests effectués et avec elle le risque de conclure à tore. La modèle de Bonferroni consiste à augmenter le
seuil d’exigence pour que le risque globale reste par exemple à α. Le nouveau risque α2 pour chaque test est
calculé comme suit :

α
α2 =
k
Cette correction possède une puissance très légèrement inférieur à la correction de Dunn-Šidák. Attention,
l’hypothèse H0 est les deux échantillons ne sont pas différent et H1 est les deux échantillons sont différent.
Il ne faut absolument pas dire si on rejette H0, les deux échantillons sont significativement différents pour
la variable V1 au risque α.

4.2 Correction de Dunn-Šidák


Vous voulez montrait qu’il existe une différence entre deux échantillon indépendant. Vous décidez faire
k tests indépendants. Votre probabilité de conclure que les deux échantillons augment avec le nombre de
tests effectués et avec elle le risque de conclure à tore. La modèle de Bonferroni consiste à augmenter le
seuil d’exigence pour que le risque globale reste par exemple à α. Le nouveau risque α2 pour chaque test est
calculé comme suit :

1
α2 = 1 − (1 − α) k

Cette correction possède une puissance très légèrement supérieur à la correction de Bonferroni. Attention,
l’hypothèse H0 est les deux échantillons ne sont pas différent et H1 est les deux échantillons sont différent.
Il ne faut absolument pas dire si on rejette H0, les deux échantillons sont significativement différents pour
la variable V1 au risque α.

Raphaël Busson (Université de Caen) GNU General Public License 11


Aide

Chapitre 5

Tests de comparaison de deux échantillons


appariés

5.1 Test signé des rangs de Wilcoxon

%let var1=; /*valeur a t0*/


%let var2=; /*valeur a t1*/
%let table=; /*table des données*/

%macro wsrtest(table, var1, var2);


data work._wsrtest;
set &table;
diff=&var1-&var2;
run;

proc univariate data=_wsrtest;


var diff;
run;

proc delete data=work._wsrtest;


run;
%mend wsrtest;
%wsrtest(table=&table, var1=&var1, var2=&var2);

12 Raphaël Busson (Université de Caen) GNU General Public License


Aide

Chapitre 6

Tests de comparaison de K échantillons


indépendants

6.1 Test ANOVA


Il faut que la variable soit quantitative.

proc anova data=table;


class var_echantillon;
model var_quantitative = var_echantillon;
run;

6.2 Test de Kruskal-Wallis


Il faut que la variable soit quantitative ou qualitatives ordinales. Si l’on peut ordonner les classe il faut
prendre le test de Jonckheere-Terpstra, page 13.

proc npar1way data=table wilcoxon;


class echantillons;
var var_quantitative_ou_ordinale;
run;

6.3 Test de Jonckheere-Terpstra


Il faut que la variable soit quantitative ou qualitatives ordinales. Les groupes doivent pouvoir être classés
dans un ordre qui a un sens. Sous ces hypothèses ce test est meilleur qu’un test de Kruskal-Wallis.

proc freq data=table;


table groupe_ordonee*variable_quantitative_ou_ordonee / jt;
run;

Raphaël Busson (Université de Caen) GNU General Public License 13


Aide SAS

6.4 Test de Cochran–Mantel–Haenszel (deux variables croisées)

proc freq data=table;


tables echantillons*var_quantitative_ou_ordinale*var_quantitative_ou_ordinale /
cmh;
run;

14 Raphaël Busson (Université de Caen) GNU General Public License


Aide

Chapitre 7

Tests de comparaison de K échantillons


indépendants (dispersion)

7.1 Test de Fisher (K=2)


Le test de Fisher est très sensible à l’hypothèse de normalité des distributions et est gourmand en calculs.

proc freq data=table;


table variable_1*variable_2;
exact fisher;
run;

7.2 Test de Bartlett


On dispose de d’une variable qualitative. Le test de Bartlett est très sensible à l’hypothèse de normalité
des distributions.

proc anova data=table;


class critere_groupe_1 critere_groupe_2;
model cible = critere_groupe_1 critere_groupe_2;
means critere_groupe_1 critere_groupe_2 / hovtest=bartlett;
run;

/*ou*/

proc glm data=table;


class critere_groupe_1 critere_groupe_2;
model cible = critere_groupe_1 critere_groupe_2;
means critere_groupe_1 critere_groupe_2 / hovtest=bartlett;
run;

Raphaël Busson (Université de Caen) GNU General Public License 15


Aide SAS

7.3 Test de Cochran


On dispose de d’une variable qualitative.

proc ttest data=table cochran;


class groupe;
var cible;
run;

7.4 Test F-max de Hartley


Le test F-max de Hartley n’est pas implémenté de base dans SAS, utiliser le test de Levene plus robuste.

7.5 Test de Levene


On dispose de d’une variable qualitative. Le test de Levene est moins sensible à l’hypothèse de normalité
des distributions que les tests de Fisher et de Bartlett.

proc anova data=table;


class critere_groupe_1 critere_groupe_2;
model cible = critere_groupe_1 critere_groupe_2;
means critere_groupe_1 critere_groupe_2 / hovtest=levene(type=abs);
run;

/*ou*/

proc glm data=table;


class critere_groupe_1 critere_groupe_2;
model cible = critere_groupe_1 critere_groupe_2;
means critere_groupe_1 critere_groupe_2 / hovtest=levene(type=abs);
run;

7.6 Test de Brown-Forsythe


On dispose de d’une variable qualitative. Le test de Brown-Forsythe est moins sensible à l’hypothèse de
normalité des distributions que les tests de Fisher et de Bartlett.

proc anova data=table;


class critere_groupe_1 critere_groupe_2;
model cible = critere_groupe_1 critere_groupe_2;
means critere_groupe_1 critere_groupe_2 / hovtest=bf;
run;

/*ou*/

16 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

proc glm data=table;


class critere_groupe_1 critere_groupe_2;
model cible = critere_groupe_1 critere_groupe_2;
means critere_groupe_1 critere_groupe_2 / hovtest=bf;
run;

7.7 Test de Klotz

proc npar1way data=table klotz;


class echantillons;
var var_quantitative_ou_ordinale;
run;

7.8 Test de Mood

proc npar1way data=table mood;


class echantillons;
var var_quantitative_ou_ordinale;
run;

Raphaël Busson (Université de Caen) GNU General Public License 17


Aide

Chapitre 8

Test d’association entre variables

8.1 Test sur le coefficient de corrélation de Pearson

proc corr data=table pearson;


var variable_quantitative_1 variable_quantitative_2;
run;

8.2 Test sur le coefficient de corrélation de Spearman

proc corr data=table spearman;


var variable_quantitative_1 variable_quantitative_2;
run;

8.3 Test sur le coefficient de corrélation Gamma de Goodman-Kruskal

proc freq data=table;


table variable_ordinale_1*variable_ordinale_2;
test gamma;
run;

8.4 Test sur le coefficient de corrélation Tau-a de Kendall

proc logistic data=table descending;


model variable_quantitative_1 = variable_quantitative_2;
run;

18 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

8.5 Test sur le coefficient de corrélation Tau-b de Kendall

proc freq data=table;


table variable_ordinale_1*variable_ordinale_2;
test kentb;
run;

/*ou*/

proc corr data=table kendall;


var variable_ordinale_1 variable_ordinale_2;
run;

Avec la proc corr vous n’aurez que les résultats du test bilatéral.

8.6 Test sur le coefficient de corrélation Tau-c de Kendall


Le Tau-c de Kendall s’appelle aussi Tau-c de Kendall-Stuart. Il s’agit d’une adaptation du Tau-b de
Kendall pour les grands échantillons.

proc freq data=table;


table variable_ordinale_1*variable_ordinale_2;
test stutc;
run;

8.7 Test sur le coefficient de dépendance de Hoeffding

proc corr data=table hoeffding;


var variable_1 variable_2;
run;

8.8 Test du χ2 de Mantel-Haenszel


Il faut que la variable soit quantitative discrète ou quantitative. On test une association linéaire des
variables. Si la variable est quantitative continue on pourra privilégier un test du log-rank page 38.

proc freq data=table;


table var_quantitative*var_quantitative_discrete / chisq;
run;

Raphaël Busson (Université de Caen) GNU General Public License 19


Aide SAS

8.9 Coefficient Kappa de Fleiss


Le coefficient Kappa de Fleiss permet de tester la concordance entre p ≥ 2 variables. Si les individus ont
tous le même poids :

proc freq data=table;


table variable_1*variable_2;
test kappa;
run;

Si les individus n’ont pas tous le même poids :

proc freq data=table;


table variable_1*variable_2;
weight pois;
test wtkap;
run;

8.10 Coefficient α de Cronbach


Ce coefficient est utilisé en psychométrie. Il étudie la cohérence interne entre les items qui composent
une dimension créé par une technique de scoring. Un α >0.7 est considéré comme acceptable. Un α >0.9 est
considéré comme souhaitable ou excellant selon les personnes.

proc corr data=table alpha;


var item_1 item_2 item_3;
run;

20 Raphaël Busson (Université de Caen) GNU General Public License


Aide

Chapitre 9

Tests suite à une régression

9.1 Recherche la meilleur puissance de la variable expliquée pour l’ex-


pliquer
9.1.1 Statistique de Box-Cox
La statistique de Box-Cox donne un coefficient lambda, qui est la puissance à laquelle il faut élever la
variable à expliquer pour minimiser la fonction de vraisemblance, et son intervalle de confiance. Dans les
faits, on regarde si 1/n est dans l’intervalle de confiance de lambda. Il faut alors élever la variable quantitative
à la puissance n. Il est plus commode de prendre un n entier pour l’interprétation des résultats.

proc transreg data=table ss2 details


plots=(transformation(dependent) scatter observedbypredicted);
model boxcox(var_explique) = identity(var_explicative)
class(var_explicative_discrete);
run;

9.1.2 Méthode par création de variables


Pour chaque variable quantitative on crée n+1 variables, la variable de la puissance 2 à n, l’exponentiel de
la variable et le log de la variable. Pensez également, qu’il est parfois plus judicieux de discrétiser la variable.
Vous gardez les variables qui vous semblent pertinentes et vous comparais les prédictions. N’oubliez pas qu’à
partir de 2 variables, pour une même dimension, l’interprétation n’est plus aussi évidente. Si l’amélioration
est faible, il vaut mieux simplifier son modèle.

9.2 Tests de normalité


Voir chapitre 1
La normalité n’est pas la chose la plus importante à vérifier. On peut parfaitement se contenter d’avoir
un résidu dont l’histogramme des fréquences est symétrique par rapport à la moyenne, avec une fréquence
diminuant à mesure que l’on s’éloigne de la moyenne et la loi dont il est extrait doit avoir une variance définie
(contre exemple loi de Cauchy). Toutes fois, même si la prédiction reste correcte, l’intervalle de confiance
calculé par SAS ne sera pas bon et donc la p-value ne sera pas la bonne.
Raphaël Busson (Université de Caen) GNU General Public License 21
Aide SAS

9.2.1 Test de symétrie


Le coefficient d’asymétrie (Skewness) et le coefficient d’aplatissement (Kurtosis) sont donnés par la com-
mande :

proc univaiate data=table;


var variable_quantitative;
run;

Voici une macro que j’ai récupéré sur le site du Mayo Clinic College of Medicine. Elle est disponible sur
cette page1 (testé le 25/09/2014). Je n’est pas réécrit la macro, elle vous est donc donnée sous un autre style
que le mien, j’ai tout de même mis mon code couleur et mon indentation pour faciliter la lecture. Elle effectue
un test de symétrie d’une distribution et suggère des transformations par élévation à une puissance pour
améliorer la symétrie. Cette macro demande un grand nombre de calculs, elle ne convient pas (actuellement)
si l’échantillon dépasse 200 individus (j’ai testé avec 150 et 300).

%let data=;
%let var=;
%let out=;

%macro symmchk(data=,var=,out=_dumpout);
%local errorflg;
%LET errorflg = 0;

%if &data= %then %do;


%put ERROR - dataset <DATA> not defined;
%LET errorflg = 1;
%end;

%if &var= %then %do;


%put ERROR - Variable <VAR> not defined;
%LET errorflg = 1;
%end;

%if &errorflg = 1 %then %do;


data _null_;
error 'ERROR - detected in the input data to the macro <surv>.';
%go to exit;
%end;

proc sql;
create table work._t as select * from dictionary.titles
where type='T';
reset noprint;
quit;

proc sql;
reset noprint;

1 www.mayo.edu/research/documents/symmchksas/doc-10027875

22 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

select nobs into :T from dictionary.tables


where libname="WORK" & memname="_T";
quit;

%LET TITLE1= ;
data _null_;
set _t;
%IF (&T>=1) %THEN %DO I=1 %TO &T;
if number=&I then call symput("TITLE&I", trim(left(text)));
%END;
run;

%LET TNEW = 1;
%LET TOTALT = %EVAL(&T + &TNEW);
%IF &TOTALT<=10 %THEN %LET TSHOW=&T;
%ELSE %LET TSHOW = %EVAL(10 - &TOTALT + &T);

%LET NEXTT1=%EVAL(&TSHOW+1);
%macro symm_out(datatemp=,chkvar=,cutp=, outd=, outp=1);

data _tmp0; set &datatemp;


varuse=&chkvar;
if varuseˆ=.;
proc sort; by varuse;

data _tmp1; set _tmp0; by varuse;


if _N_=1 then do; newidx=0; retain newidx; end;
newidx=newidx+1;
dummy=1;
keep newidx varuse dummy;
proc sort; by dummy;
proc means noprint data=_tmp1; var varuse; by dummy;
output out=_ddd mean=varmean median=varmed skewness=varskew std=varstd
Q1=q1 Q3=q3 N=totaln;
proc univariate noprint data=_tmp1; var varuse; by dummy;
output out=_ddd2 pctlpts=12.5 87.5 pctlpre=new;
proc univariate noprint data=_tmp1; var varuse; by dummy;
output out=_ddd3 pctlpts=0 1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
pctlpre=dum;

proc univariate noprint data=_tmp1; var varuse; by dummy;


output out=_ddd4 pctlpts=100 99 98 97 96 95 94 93 92 91 90
89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71
70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51
pctlpre=dum;

data _ddd5; merge _ddd3 _ddd4 _ddd; by dummy;


if first.dummy then do;

Raphaël Busson (Université de Caen) GNU General Public License 23


Aide SAS

id=0; retain id; end;


keep id x dummy varmed varstd totaln;
id=id+1; x=(dum100+dum0)/2; output;
id=id+1; x=(dum99+dum1)/2; output;
id=id+1; x=(dum98+dum2)/2; output;
id=id+1; x=(dum97+dum3)/2; output;
id=id+1; x=(dum96+dum4)/2; output;
id=id+1; x=(dum95+dum5)/2; output;
id=id+1; x=(dum94+dum6)/2; output;
id=id+1; x=(dum93+dum7)/2; output;
id=id+1; x=(dum92+dum8)/2; output;
id=id+1; x=(dum91+dum9)/2; output;
id=id+1; x=(dum90+dum10)/2; output;
id=id+1; x=(dum89+dum11)/2; output;
id=id+1; x=(dum88+dum12)/2; output;
id=id+1; x=(dum87+dum13)/2; output;
id=id+1; x=(dum86+dum14)/2; output;
id=id+1; x=(dum85+dum15)/2; output;
id=id+1; x=(dum84+dum16)/2; output;
id=id+1; x=(dum83+dum17)/2; output;
id=id+1; x=(dum82+dum18)/2; output;
id=id+1; x=(dum81+dum19)/2; output;
id=id+1; x=(dum80+dum20)/2; output;
id=id+1; x=(dum79+dum21)/2; output;
id=id+1; x=(dum78+dum22)/2; output;
id=id+1; x=(dum77+dum23)/2; output;
id=id+1; x=(dum76+dum24)/2; output;
id=id+1; x=(dum75+dum25)/2; output;
id=id+1; x=(dum74+dum26)/2; output;
id=id+1; x=(dum73+dum27)/2; output;
id=id+1; x=(dum72+dum28)/2; output;
id=id+1; x=(dum71+dum29)/2; output;
id=id+1; x=(dum70+dum30)/2; output;
id=id+1; x=(dum69+dum31)/2; output;
id=id+1; x=(dum68+dum32)/2; output;
id=id+1; x=(dum67+dum33)/2; output;
id=id+1; x=(dum66+dum34)/2; output;
id=id+1; x=(dum65+dum35)/2; output;
id=id+1; x=(dum64+dum36)/2; output;
id=id+1; x=(dum63+dum37)/2; output;
id=id+1; x=(dum62+dum38)/2; output;
id=id+1; x=(dum61+dum39)/2; output;
id=id+1; x=(dum60+dum40)/2; output;
id=id+1; x=(dum59+dum41)/2; output;
id=id+1; x=(dum58+dum42)/2; output;
id=id+1; x=(dum57+dum43)/2; output;
id=id+1; x=(dum56+dum44)/2; output;
id=id+1; x=(dum55+dum45)/2; output;
id=id+1; x=(dum54+dum46)/2; output;
id=id+1; x=(dum53+dum47)/2; output;

24 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

id=id+1; x=(dum52+dum48)/2; output;


id=id+1; x=(dum51+dum49)/2; output;
proc sort; by dummy id;

data _ddd6; set _ddd5; by dummy id;


keep s5 overtm dummy;
if first.dummy then do;
overtm=0; retain overtm; end;
if abs(x-varmed)<=1.96*varstd/sqrt(totaln) then overtm=overtm+1;
if last.dummy then do;
s5=overtm/50;
output;
end;

data _tmp2; merge _tmp1(in=in1) _ddd _ddd2 _ddd6; by dummy;


if newidx<=totaln/2 then do; pick=1; varnew=varmed-varuse; end;
if newidx> totaln/2 then do; pick=2; varnew=varuse-varmed; end;
s3=(q1-varmed*2+q3)/(q3-q1);
s3p=(new12_5-varmed*2+new87_5)/(new87_5-new12_5);
proc sort; by newidx;

data _tmp3; set _tmp2 end=eof; by newidx;


keep newidx w1 w2 w3 w4 totaln varmean varskew skew1 dblsum trisum s3 s3p;
label s3=S4
s3p=S4';
if newidx=1 then do;
w2=0; w3=0; w4=0; w1=0; trisum=0; dblsum=0;
retain w1 w2 w3 w4 trisum dblsum;
end;
w1=w1+varuse;
trisum=trisum+(varuse-varmean)**3;
dblsum=dblsum+(varuse-varmean)**2;
if newidx>=2 then do;
w2=w2+(newidx-1)*varuse;
end;
if newidx>=3 then do;
w3=w3+(newidx-1)*(newidx-2)*varuse;
end;
if newidx>=4 then do;
w4=w4+(newidx-1)*(newidx-2)*(newidx-3)*varuse;
end;
if eof then do;
w1=w1/totaln;
w2=w2/(totaln*(totaln-1));
w3=w3/(totaln*(totaln-1)*(totaln-2));
w4=w4/(totaln*(totaln-1)*(totaln-2)*(totaln-3));
skew1=(trisum/totaln)/((dblsum/totaln)**1.5);
output;
end;
lable skew1="S1";

Raphaël Busson (Université de Caen) GNU General Public License 25


Aide SAS

data _tmp4; set _tmp3;


w5=2*w2-w1;
w6=6*w3-6*w2+w1;
w7=20*w4-30*w3+12*w2-w1;
skew2=w6/w5;
skew3=(1+skew2)/(1-skew2);
skew4=w7/w5;
label w5="l2"
w6="l3"
w7="l4"
skew2="S2"
skew3="S2'"
varmean="Mean";

data _tmp6; set _tmp2;


drop dummy varmean varskew;

data _tmp7; set _tmp6(keep=newidx varuse totaln s5);


i1=newidx; x1=varuse;
if 0<i1<=totaln-2;
do i=i1+1 to totaln-1;
set _tmp6 point=I nobs=totalnn;
i2=i; x2=varuse;
do j=i2+1 to totaln;
set _tmp6 point=j nobs=totalnn;
i3=j; x3=varuse;
output;
end;
end;
drop varuse;
proc sort; by i1 i2 i3;

data _tmp8_1; set _tmp7(keep=x1 x2 x3 i1 i2 i3 s5 totaln);


if _N_=1 then do; lft=0; rght=0; retain lft rght; end;
s1=sign(int((x1+x2-2*x3)*10000000000)/10000000000);
s2=sign(int((x1+x3-2*x2)*10000000000)/10000000000);
s3=sign(int((x2+x3-2*x1)*10000000000)/10000000000);
f=s1+s2+s3;
if f=1 then rght=rght+1;
if f=-1 then lft=lft+1;
run;

proc datasets;
delete _tmp7 _tmp6 _tmp3 _tmp2 _tmp1 _tmp0 _ddd _ddd2
_ddd3 _ddd4 _ddd5 _ddd6;
run;
quit;

data _tmp9; set _tmp8_1(keep=totaln rght lft s5) end=eof;

26 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

if eof then do;


T=rght-lft;
output;
end;

proc sort data=_tmp8_1; by i1;


proc means data=_tmp8_1 noprint; var f; by i1;
output out=_dd1 sum=sum11;
proc sort data=_tmp8_1; by i2;
proc means data=_tmp8_1 noprint; var f; by i2;
output out=_dd2 sum=sum12;
proc sort data=_tmp8_1; by i3;
proc means data=_tmp8_1 noprint; var f; by i3;
output out=_dd3 sum=sum13;

data _dd1; set _dd1; i=i1; proc sort; by i;


data _dd2; set _dd2; i=i2; proc sort; by i;
data _dd3; set _dd3; i=i3; proc sort; by i;
data _ddda; merge _dd1 _dd2 _dd3; by i;
bi=sum(sum11,sum12,sum13);
bi2=bi*bi;
proc means noprint; var bi2;
output out=_bsum sum=bsum;

proc sort data=_tmp8_1; by i2 i3;


proc means data=_tmp8_1 noprint; var f; by i2 i3;
output out=_dd23 sum=sum23;
proc sort data=_tmp8_1; by i1 i3;
proc means data=_tmp8_1 noprint; var f; by i1 i3;
output out=_dd13 sum=sum13;
proc sort data=_tmp8_1; by i1 i2;
proc means data=_tmp8_1 noprint; var f; by i1 i2;
output out=_dd12 sum=sum12;

data _dd1; set _dd23; i=i2; j=i3; proc sort; by i j;


data _dd2; set _dd13; i=i1; j=i3; proc sort; by i j;
data _dd3; set _dd12; i=i1; j=i2; proc sort; by i j;
data _dddb; merge _dd1 _dd2 _dd3; by i j;
bi=sum(sum12,sum13,sum23);
bi2=bi*bi;
proc means noprint; var bi2;
output out=_bsum2 sum=bsum2;

proc datasets;
delete _tmp8_1 _ddda _dddb _dd23 _dd13 _dd12 _dd1 _dd2 _dd3;
run;
quit;

data _tmp10; merge _tmp9 _bsum _bsum2 _tmp4;


term1=(totaln-3)*(totaln-4)/(totaln-1)/(totaln-2)*bsum;

Raphaël Busson (Université de Caen) GNU General Public License 27


Aide SAS

term2=(totaln-3)/(totaln-4)*bsum2;
term3=(totaln-1)*(totaln-2)*totaln/6;
term4=(totaln-3)*(totaln-4)*(totaln-5)/totaln/(totaln-1)/(totaln-2);
Var=TERM1+TERM2+TERM3-(1.0-TERM4)*T*T;
skew4=T/sqrt(var);
prob=2*(1.0-probnorm(abs(skew4)));
call symput('cutp',prob);

label skew4="S3 : NP symmetry Test"


prob= "S3 : P-value "
skew1="S1 : Sample Skewness"
skew2="S2 : L-Skewness I"
skew3="S2': L-Skewness II";
label s3= "S4 : Quartile Skewness"
s3p= "S4': Octile Skewness"
totaln="N"
s5= "S5 : New Method";

%if &outp=1 %then %do;

data _tmp11; set _tmp10;


file print;
put " ";
put " ";
put @35 "N = " totaln 10.0;
put @35 "S1 : Sample Skewness = " skew1 10.7;
put @35 "S2 : L-Skewness I = " skew2 10.7;
put @35 "S2': L-Skewness II = " skew3 10.7;
put @35 "S3 : NP Symmetry Test = " skew4 10.7;
put @35 "S3 : P-value = " prob 10.4;
put @35 "S4 : Quartile Skewness= " s3 10.7;
put @35 "S4': Octile Skewness = " s3p 10.7;
put @35 "S5 : New Method = " s5 10.7;
%end;

data &outd; set _tmp10;


keep totaln skew1 skew2 skew3 s3 s3p skew4 prob s5;
run;

proc datasets nolist lib=work;


delete _tmp4 _tmp9 _tmp10 _bsum _bsum2;
run;

%mend symm_out;

data _use1; set &data;


title&NEXTT1 "Check &var";
newvar1=&var;
newvar2=&var**2;
newvar3=&var**3;

28 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

newvar4=&var**4;
newvar5=&var**(1./2);
newvar6=&var**(1./3);
newvar7=&var**(1./4);
newvar8=log(&var+1);
newvar9=(&var+1)**(-1./2);
newvar10=(&var+1)**(-1./3);
newvar11=(&var+1)**(-1./4);
newvar12=1./(&var+1);
newvar13=1./(&var+1)**2;
newvar14=1./(&var+1)**3;
newvar15=1./(&var+1)**4;

%local cutpp;

%symm_out(datatemp=_use1,chkvar=newvar1,cutp=&cutpp,outd=_out1,outp=1);

%if .<&cutpp< 0.05 %then %do;


%symm_out(datatemp=_use1,chkvar=newvar2,cutp=cutppp,
outd=_out2,outp=0);
%symm_out(datatemp=_use1,chkvar=newvar3,cutp=cutppp,
outd=_out3,outp=0);
%symm_out(datatemp=_use1,chkvar=newvar4,cutp=cutppp,
outd=_out4,outp=0);
%symm_out(datatemp=_use1,chkvar=newvar5,cutp=cutppp,
outd=_out5,outp=0);
%symm_out(datatemp=_use1,chkvar=newvar6,cutp=cutppp,
outd=_out6,outp=0);
%symm_out(datatemp=_use1,chkvar=newvar7,cutp=cutppp,
outd=_out7,outp=0);
%symm_out(datatemp=_use1,chkvar=newvar8,cutp=cutppp,
outd=_out8,outp=0);
%symm_out(datatemp=_use1,chkvar=newvar9,cutp=cutppp,
outd=_out9,outp=0);
%symm_out(datatemp=_use1,chkvar=newvar10,cutp=cutppp,
outd=_out10,outp=0);
%symm_out(datatemp=_use1,chkvar=newvar11,cutp=cutppp,
outd=_out11,outp=0);
%symm_out(datatemp=_use1,chkvar=newvar12,cutp=cutppp,
outd=_out12,outp=0);
%symm_out(datatemp=_use1,chkvar=newvar13,cutp=cutppp,
outd=_out13,outp=0);
%symm_out(datatemp=_use1,chkvar=newvar14,cutp=cutppp,
outd=_out14,outp=0);
%symm_out(datatemp=_use1,chkvar=newvar15,cutp=cutppp,
outd=_out15,outp=0);

data &out; set _out1(in=in1) _out2(in=in2) _out3(in=in3) _out4(in=in4)


_out5(in=in5) _out6(in=in6) _out7(in=in7) _out8(in=in8) _out9(in=in9)
_out10(in=in10) _out11(in=in11) _out12(in=in12) _out13(in=in13)

Raphaël Busson (Université de Caen) GNU General Public License 29


Aide SAS

_out14(in=in14) _out15(in=in15);
if in1 then do; cat=1 ; lab="Original "; end;
if in2 then do; cat=2 ; lab="Square "; end;
if in3 then do; cat=3 ; lab="3rd power "; end;
if in4 then do; cat=4 ; lab="4th power "; end;
if in5 then do; cat=5 ; lab="square root"; end;
if in6 then do; cat=6 ; lab="3rd root "; end;
if in7 then do; cat=7 ; lab="4th root "; end;
if in8 then do; cat=8 ; lab="log "; end;
if in9 then do; cat=9 ; lab="1/square rt"; end;
if in10 then do; cat=10; lab="1/3rd root "; end;
if in11 then do; cat=11; lab="1/4th root "; end;
if in12 then do; cat=12; lab="1/original "; end;
if in13 then do; cat=13; lab="1/square "; end;

if in14 then do; cat=14; lab="1/3rd power"; end;


if in15 then do; cat=15; lab="1/4th power"; end;
label lab="Tranform EQ";
title&NEXTT1 "Check &var";
keep cat lab skew1 skew2 skew3 skew4 prob s3 s3p s5;
proc sort; by cat;
proc print label;
var lab skew1 skew2 skew3 skew4 prob s3 s3p s5;
run;

%end;

title1;
%IF (&T>=1) %THEN %DO I=1 %TO &T;
title&I "&&TITLE&I";

%END;
%exit:
run;

%mend symmchk;
%symmchk(data=&data,var=&var,out=&out);

9.3 Tests de tolérance et variance inflation factors (VIF)


La tolérance (T ol) et la variance inflation factors (V IF ) sont équivalents puisque :
1
V IF =
T ol
De façon empirique, on convient que pour V IF =1, on se trouve dans le meilleur des cas. Les variables
ne sont pas du tout corrélés. Si V IF >5, la corrélation est forte et il convient de s’interroger sur les liens qui
unissent certaines variables. On peut effectuer des regroupements dans le cas de variables discrètes. Vérifiez
que les prédictions ne sont pas meilleures sans l’une des variables incriminées. Si V IF >10, il faut faire
quelque chose. Le modèle ne doit pas rester dans l’état. Attention, il est évident que dans le cas de termes
30 Raphaël Busson (Université de Caen) GNU General Public License
Aide SAS

d’interactions la limite est facilement franchie puisque les termes sont évidemment corrélés, avec les variables
composant le terme d’interactions. Il faut ignorer ce critère pour les termes d’interactions si l’une
des variables principales est dans le modèle.
La fonction glm ne donne que la tolérance de type I et de type II. La tolérance pour le calcul du V IF
est la tolérance de type II.

proc glm data=table;


class var_explicative_discrete;
model var_explique = var_explicative_discrete var_explicative / tolerance;
run;

9.4 Tests sur la présence d’individus trop influents


9.4.1 Distance de Cook (meilleur)
Il existe plusieurs seuils pour considérer qu’un individu est trop influent Le seuil historique est à 1. Ce
seuil est assez mauvais car trop restrictif. Il est d’autant plus restrictif qu’il y a d’observation. Un autre seuil
a été fixé à nb_obs
4
. Ce seuil est vraiment bon. Ce seuil a été ajusté et est devenu nb_obs−1−ddl
4
. Je ne suis pas
sûr que l’ajustement soit efficace. Je pense même que c’est nuisible. J’ai pour ma part créé un seuil personnel
et non-validé. J’ai fixé ce seuil à 2 × moyenne{distance de Cook}. Pour moi, évidement, c’est le meilleur
seuil. Il a largement battu les autres seuils quand la proportion d’anomalie dépasse les 5%. En dessous de
5%, les seuils nb_obs
4
et nb_obs−1−ddl
4
sont bien meilleur en spécificité.

proc glm data=table;


model var_cible = list_var_explicative;
output out=nom_table_sorties_stat cookd=nom_var_cookd ;
run;

9.4.2 R-Student (très bon)


Seuil |R-Student| > 2

proc glm data=table;


model var_cible = list_var_explicative;
output out=nom_table_sorties_stat rstudent=nom_var_rstudent ;
run;

9.4.3 DFFITS (très bon)


q
Seuil |DFFITS| > 2 nb_obs
ddl

proc glm data=table;


model var_cible = list_var_explicative;
output out=nom_table_sorties_stat dffits=nom_var_dffits ;
run;

Raphaël Busson (Université de Caen) GNU General Public License 31


Aide SAS

9.4.4 Covariance ratio (bon)


Seuil |Covariance ratio − 1| > 3 nb_obs
ddl

proc glm data=table;


model var_cible = list_var_explicative;
output out=nom_table_sorties_stat covratio=nom_var_covratio ;
run;

9.5 Tests de stabilité des coefficients (avec distance de Cook)


On peut se faire une idée de la stabilité de notre modèle en supprimant les individus les plus influant et
en vérifiant que les coefficients ne changent pas trop. Vous pouvez faire un clique droit ici pour enregistrer
la macro.

%let table=; /*table*/


%let id=; /*identifiant*/
%let var_explicative=; /*variables du modele*/
%let cible=; /*variable a explique*/
%let alpha_influence=; /*distance de Cook max (1 [mauvais], 4/nb_obs, 4/(nb_obs-1-ddl))*/
/*perso je prend 2*moyenne des distences de cook (Attention c’est purement personel)*/
%let class=; /*variables expliquatives qualitatives*/

%macro stabi_coef(table, id, cible, var_explicative, alpha_influence=1,class=);


proc glmselect data=&table;
class &class;
model &cible = &var_explicative / selection=none;
run;
quit;

proc glm data=&table noprint;


class &class;
model &cible = &var_explicative;
output out=work._stabi_coef_out_res cookd=cookd;
run;

data work._stabi_coef_out_res (keep=&id cookd);


set work._stabi_coef_out_res;
where cookd>&alpha_influence;
output;
run;

data _null_;
set work._stabi_coef_out_res;
call symput("row",_n_);
if n>1 then call symput("suppr"||left(_n_), ",'"||left(&id)||left("'"));
else call symput("suppr"||left(_n_), "'"||left(&id)||left("'"));
run;

32 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

%let suppr=;
%do i =1 %to &row;
%let suppr=&suppr &&suppr&i;
%end;

data work._stabi_coef_out_res;
set &table;
if &id not in (&suppr) then output;
run;

proc glmselect data=work._stabi_coef_out_res;


class &class;
model var_explique = &var_explicative / selection=none;
run;

proc delete data=work._stabi_coef_out_res;


run;
%mend stabi_coef;

%stabi_coef (
table=&table, id=&id, cible=&cible, var_explicative=&var_explicative,
alpha_influence=&alpha_influence, class=&class
);

9.6 Comparer deux modèles avec un test Anova


Un test Avona va permettre de comparer deux modèles emboîtés.

proc anova data=table;


class list_var_petit_modele list_var_sup_grand_modele;
model var_cible=list_var_petit_modele list_var_sup_grand_modele;
test h=list_var_petit_modele e=list_var_sup_grand_modele;
run;

Raphaël Busson (Université de Caen) GNU General Public License 33


Aide

Chapitre 10

Tests suite à une régression logistique

10.1 Comparaison de 2 courbes ROC


10.1.1 Sur la partie d’apprentissage
On va utiliser le test de DeLong, DeLong and Clarke-Pearson.

proc logistic data=table plots(only)=(roc);


class var_modele_discrete_1 var_modele_discrete_2;
modele_total:model var_cible=var_modele_1 var_modele_discrete_1
var_modele_2 var_modele_discrete_2 / selection=none;
roc 'modele 1' var_modele_1 var_modele_discrete_1;
roc 'modele 2' var_modele_2 var_modele_discrete_2;
roccontrast reference('modele 1') / estimate=allpairs e cov;
run;

10.1.2 Sur la partie de validation


On va utiliser le test de DeLong, DeLong and Clarke-Pearson. Vous pouvez faire un clique droit ici pour
enregistrer la macro.

%let ap=; /*table d’apprentissage*/


%let vali=; /*table de validation*/

/*attention ne pas faire :


(%let ap=table (where=(vali=0)); %let vali=table (where=(vali=1));)
un bug de sas est observe. il faut creer deux tables*/

%let id=; /*identufiante des individus*/


%let var1=; /*variables modele 1*/
%let var2=; /*variables modele 2*/
%let cible=; /*variable de classification*/
%let class=; /*variables qualitatives*/
%let lib=; /*librerie de travail*/

34 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

%macro roc_comp(id, ap, vali, cible, var1, var2, class=, lib=work);


%local c1;
%local c2;
%local test;
%local formc;

proc contents data=&lib..&ap (keep=&cible) out=work._roc_comp_out_f noprint;


run;

data _null_;
set work._roc_comp_out_f;
call symput('test', n(format));
call symput('formc', format);
run;

%if &test=1 %then %do;


proc format fmtlib cntlout=work._roc_comp_t;
run;

data _null_;
set work._roc_comp_t (where=(fmtname="&formc"));
call symput(cats('c', _n_), label);
run;
%end;
%else %do;
proc freq data=&ap noprint;
table &cible / out=work._roc_comp_t;
run;

data _null_;
set work._roc_comp_t (where=(n(&cible)=1));
call symput(cats('c', _n_), cats(&cible));
run;
%end;

proc logistic data=&lib..&ap noprint;


class &class;
model &cible=&var1 / selection=none;
score data=&lib..&vali out=work._roc_comp_p1;
run;

proc logistic data=&lib..&ap noprint;


class &class;
model &cible=&var2 / selection=none;
score data=&lib..&vali out=work._roc_comp_p2;
run;

data work._roc_comp_p (keep=&id p_&c1 p_&c2 p2_&c1 p2_&c2 &cible);


merge work._roc_comp_p1 work._roc_comp_p2
(rename=(p_&c1=p2_&c1 p_&c2=p2_&c2));

Raphaël Busson (Université de Caen) GNU General Public License 35


Aide SAS

by &id;
run;

proc logistic data=work._roc_comp_p;


modele_total:model &cible=p_&c1 p_&c2 p2_&c1 p2_&c2
/ selection=none;
roc 'roc modele 1' p_&c1 p_&c2;
roc 'roc modele 2' p2_&c1 p2_&c2;
roccontrast reference('roc modele 1') / estimate=allpairs e cov;
run;

proc datasets library=work nolist;


delete _roc_comp_:(gennum=all);
run;
%mend roc_comp;
%roc_comp(
id=&id, ap=&ap, vali=&vali, cible=&cible,
var1=&var1, var2=&var2, class=&class, lib=&lib
);

10.2 Test de Hosmer-Lemeshow


Le test de Hosmer-Lemeshow teste la bonne qualité de l’ajustement. L’hypothèse H0 est que l’ajustement
est de bonne qualité.

proc logistic data=table;


class list_var_qualitatives;
model var_cible=list_var_quantitatives list_var_qualitatives / lackfit selection=none;
run;

10.3 Tests de tolérance et variance inflation factors (V IF )


De façon empirique, on convient que pour V IF =1, on se trouve dans le meilleur des cas. Les variables
ne sont pas du tout corrélés. Si V IF >5, la corrélation est forte et il convient de s’interroger sur les liens qui
unissent certaines variables. On peut effectuer des regroupements dans le cas de variables discrètes. Vérifiez
que les prédictions ne sont pas meilleures sans l’une des variables incriminées. Si V IF >10, il faut faire
quelque chose. Le modèle ne doit pas rester dans l’état. Attention, il est évident que dans le cas de termes
d’interactions la limite est facilement franchie puisque les termes sont évidemment corrélés, avec les variables
composant le terme d’interactions. Il faut ignorer ce critère pour les termes d’interactions si l’une
des variables principales est dans le modèle.
La proc logistic ne donne ni la tolérance ni le V IF . Il faut donc passer par la proc glm. La proc glm
ne donne que la tolérance de type I et de type II. La tolérance pour le calcul du V IF est la tolérance de
type II. Vous pouvez faire un clique droit ici pour enregistrer la macro.

%let table=;/*table de donnee*/


%let var_explique=;/*variable cible*/

36 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

%let var_explicative_discrete=;/*liste des variables quantitatives explicatives*/


%let var_explicative=;/*liste de variable qualitatives explicative*/

%macro logtol(table, var_explique, var_explicative_discrete, var_explicative);


proc logistic data=&table;
class &var_explicative_discrete;
model &var_explique = &var_explicative_discrete &var_explicative / selection=none;
output out=work._logtol_out pred=_p;
run;

data work._logtol_out;
set work._logtol_out;
w=_p*(1-_p);
run;

proc glm data=_logtol_out;


weight w;
class &var_explicative_discrete;
model &var_explique = &var_explicative_discrete &var_explicative / tolerance;
run;

proc datasets library=work nolist;


delete _logtol_:(gennum=all);
run;
%mend logtol;

%logtol(table=&table, var_explique=&var_explique,
var_explicative_discrete=&var_explicative_discrete, var_explicative=&var_explicative);

Raphaël Busson (Université de Caen) GNU General Public License 37


Aide

Chapitre 11

Test comparaison de deux courbes de sur-


vies

11.1 Log-rank
Ce test est un teste du log-rank. Dans le code suivant la variable var_temps prend la date de survenue
de d’événement (le décès), ou le délai avant la survenue de l’événement ; ou pour les personnes qui n’ont
pas eu la survenue de cette événement la date ou le délai à partir duquel on censure l’individu (perd leurs
traces, changement d’adresse, arrêt de l’étude...). La variable var_censure prend des valeurs numériques.
On défini une liste de valeurs correspondantes aux différentes censures possibles. Dans l’exemple suivant les
valeurs sont 1 et 2. On peut parfaitement définir une seule valeur pour tous les types de censures. La variable
var_strate permet de différencier les individus des deux groupes.
Pour le test en lui même, il est conseillé d’observer la p-value du Log-rang.

proc lifetest data=table plots=(s,ls,lls);


time var_temps*var_censure(1,2);
strata var_strate;
id identifiant;
run;

11.2 Log-rank de Peto (le meilleurs)

proc lifetest data=table plots=(s,ls,lls);


time var_temps*var_censure(1,2);
strata var_strate / test=peto;
id identifiant;
run;

11.3 Prentice-Wilcoxon (le plus sensible)


developed by Lashley, et al. (2000).
38 Raphaël Busson (Université de Caen) GNU General Public License
Aide SAS

%macro tim2evnt(dsn,tim2evnt,censor,treat1);
*************************************;
** Macro to compute Prentice-Wilcoxon;
** test for pair-matched data.;
** STATKING Consulting, Inc.;
** October 199;
** dsn= data set name;
** tim2evnt = variable containing;
** time to event information;
** censor = variable containing;
** censor information;
** treat1 = value of first treatment;
*************************************;
proc sort data=&dsn; by &tim2evnt;
run; ** compute s_sub_i and score for each point;
data &dsn; set &dsn nobs=nobs;
retain s_sub_i 1;
** get time to event for last obs;
lasttime=lag(&tim2evnt);
** compute s_sub_i;
if ((lasttime ˆ= &tim2evnt) and (&censor ˆ= 1)) then
** nsubj / (nsubj+1);
s_sub_i=s_sub_i*((nobs-_n_+1)/(nobs-_n_+2));
** compute score;
if (&censor=1) then score=1-s_sub_i;
else score=1-(2*s_sub_i);
drop lasttime;
run;
proc sort data=&dsn; by subject treatmnt;
run;

data &dsn; set &dsn end=eof; by subject treatmnt;


** y1 is score and censor info for first treatmnt;
** y2 is score and censor info for second treatmnt;
length y1 8y2 8;
retain y1 y2 surv1 surv2 score1 score2;
retain sumd 0 sumd2 0;
** get scores for treatment 1 and censoring info;
if treatmnt= "&treat1" then do;
score1=score;
if censor=1 then y1=put(&tim2evnt,5.2)||’+’;
else y1=put(&tim2evnt,5.2);
surv1=s_sub_i;
end;
else do;
** get scores for treatment 2 and censoring info;
score2=score;
if censor=1 then y2=put(&tim2evnt,5.2)||'+';
else y2=put(&tim2evnt,5.2);
surv2=s_sub_i;

Raphaël Busson (Université de Caen) GNU General Public License 39


Aide SAS

end;
** compute delta_sub_l, sum of delta_sub_l
and; ** sum of delta_sub_l squared;
if last.subject then do;
delta=score1-score2;

delta2=delta**2;
if (delta ˆ= .) then do;
sumd=sumd+delta;
sumd2=sumd2+delta2;
end;
** output scores and summations;
output;
end;
** end of data, compute z statistic and probability;
if eof=1 then do;
z=sumd/(sqrt(sumd2));
probz=2*(1-probnorm(abs(z)));
call symput('z',put(z,4.2));
call symput('probz',put(probz,6.4));
end;
drop &tim2evnt score treatmnt &censor z probz;
run;
%mend tim2evnt;

%tim2evnt(dsn=data, tim2evnt=hours, censor=censor,


treat1=PLACEBO);

40 Raphaël Busson (Université de Caen) GNU General Public License


Aide

Chapitre 12

Analyses intermédiaires

12.1 Introduction
On effectue des analyse intermédiaire pour pouvoir arrêter une étude si les tests sont concluant avant la
fin. On économise du temps et de l’argent.
La correction de Bonferonni et de Dunn-Šidák ne s’applique pas ici car les tests ne sont pas dépendant
car une partie des individus qui sont testé au test n + 1 ont été testé au test n.

12.2 Correction de Pocock (non-recommandé)


C’est une adaptation de la correction de Bonferonnie qui tient compte de la non-indépendance des
échantillon. On cherche un risque α2 tel que, si l’on effectue nos k test tout les n individus avec ce risque, le
risque global soit de α. Par simulation avec des groupes de 100 individus et entre 20000 et 40000 simulation,
on obtient les résultats du tableau 12.1.

α global avec α corrigé α = 5% pour analyse finale


Nombre d’analyse α corrigé
Estimation IC 95% Estimation IC 95%
2 0.02950 0.0507 [0.0485 ; 0.0528] 0.0503 [0.0481 ; 0.0524]
3 0.02212 0.0496 [0.0475 ; 0.0517] 0.0496 [0.0475 ; 0.0517]
4 0.01822 0.0504 [0.0483 ; 0.0525] 0.0498 [0.0477 ; 0.0519]
5 0.01580 0.0508 [0.0483 ; 0.0533] 0.0507 [0.0482 ; 0.0532]
6 0.01450 0.0502 [0.0472 ; 0.0532] 0.0506 [0.0475 ; 0.0536]

Tab. 12.1: α corrigé par la méthode de Pocock

Sas ne donne pas le α corrigé mais les borne du test centré réduit.

proc seqdesign;
design nstages=4 /*nombre de tests*/
method=poc
alt=twosided /*ou lower, upper*/
stop=both
/*si l’on veux des bornes d’arret pour non amelioration et non degradation*/
alpha=0.05 beta=0.10;
run;

Raphaël Busson (Université de Caen) GNU General Public License 41


Aide SAS

Nombre d’analyse α corrigé Borne


2 0.03296 2.13251
3 0.02549 2.23385
4 0.02125 2.30350
5 0.01845 2.35644
6 0.01645 2.39870

Tab. 12.2: Valeur théorique des α corrigés par la méthode de Pocock

12.3 Correction de O’Brien et Flemming


La méthode de O’Brien et Flemming utilise un risque fortement croisant avec un risque de départ très
bas.

proc seqdesign;
design nstages=4 /*nombre de tests*/
method=obf
alt=twosided /*ou lower, upper*/
stop=both
/*si l’on veux des bornes d’arret pour non amelioration et non degradation*/
alpha=0.05 beta=0.10;
run;

Nombre d’analyse Analyse α corrigé Borne


1 0.00562 2.76864
2
2 0.05118 1.95773
1 0.00064 3.41422
3 2 0.01577 2.41422
3 0.04870 1.97120
1 0.00007 3.95831
2 0.00513 2.79895
4
3 0.02229 2.28533
4 0.04780 1.97915
1 0.00001 4.44899
2 0.00166 3.14591
5 3 0.01021 2.56862
4 0.02612 2.22449
5 0.04663 1.98965

Tab. 12.3: Valeur théorique des α corrigés par la méthode de O’Brien et Flemming

12.4 Correction de Lan et Demets (Pocok)


La méthode de Lan et Demets (Pocok) et entre la méthode de Pocok et celle de O’Brien et Flemming.
42 Raphaël Busson (Université de Caen) GNU General Public License
Aide SAS

proc seqdesign;
design nstages=4 /*nombre de tests*/
method=errfuncpoc
alt=twosided /*ou lower, upper*/
stop=both
/*si l’on veux des bornes d’arret pour non amelioration et non degradation*/
alpha=0.05 beta=0.10;
run;

12.5 Correction de Lan et Demets (O’Brien et Flemming)


La méthode de Lan et Demets (O’Brien et Flemming) et entre la méthode de Pocok et celle de O’Brien
et Flemming.

proc seqdesign;
design nstages=4 /*nombre de tests*/
method=errfuncobf
alt=twosided /*ou lower, upper*/
stop=both
/*si l’on veux des bornes d’arret pour non amelioration et non degradation*/
alpha=0.05 beta=0.10;
run;

12.6 Correction power family

proc seqdesign;
design nstages=4 /*nombre de tests*/
method=pow(rho=0.25) /*0 Pocok, 0.25 O’Brien et Flemming */
alt=twosided /*ou lower, upper*/
stop=both
/*si l’on veux des bornes d’arret pour non amelioration et non degradation*/
alpha=0.05 beta=0.10;
run;

12.7 Correction de Peto - Haybittle


Cette méthode consiste augmenté le risque très légèrement en utilisant un α2 = 0 .001 pour les analyses
intermédiaires et α = 0 .05 pour l’analyse finale. Le risque globale est très proche de 0 .05 et fait disparaitre
le paradoxe d’une analyse final significative non prise en compte à cause d’analyses intermédiaires effectuées.

proc seqdesign;
design nstages=4 /*nombre de tests*/
method=peto(z=3.89) /*alpha_2*/

Raphaël Busson (Université de Caen) GNU General Public License 43


Aide SAS

alt=twosided /*ou lower, upper*/


stop=both
/*si l’on veux des bornes d’arret pour non amelioration et non degradation*/
alpha=0.05 beta=0.10;
run;

12.8 Méthode de triangulation

proc seqdesign;
design nstages=4 /*nombre de tests*/
method=tri(tau=1)
alt=twosided /*ou lower, upper*/
stop=both
/*si l’on veux des bornes d’arret pour non amelioration et non degradation*/
alpha=0.05 beta=0.10;
run;

44 Raphaël Busson (Université de Caen) GNU General Public License


Aide

Chapitre 13

Tests de comparaison de deux échantillons


non-homogène avec score de propension

13.1 Introduction
Pour ce genre de comparaison on utilise le score de propension. Le score de propension est la probabilité
qu’un sujet appartienne apriori, au groupe qui a subi une intervention, étant données ses caractéristiques.

13.2 Par la modification des poids


Les individus sont pondéré par l’inverse du score de propension, pour ceux du groupe intervention et
l’inverse de 1 moins leur score de propension, pour les autres. On peut également normaliser le poids. Il y
a un risque de sur-pondérer un individu. Exemple un individu a reçu un traitement pour lequel on savait
qu’il était allergique. Il en meure. Sa mort aura un poids très importent car la probabilité qu’il reçoive le
traitement était proche de 0.
Une autre méthode consiste à attribuer un poids de 1 pour les individus du premier groupe et 1 moins
le score de propension sur le score de propension pour les individus du deuxième groupe.
Dans le code suivant, le poids est égale à l’inverse du score de propension normalisé. La variable group
vaut 0 ou 1.

proc logistic descending data=table;


title 'Propensity Score Estimation';
model group=var1-var3/lackfit outroc=ps_r;
output out=ps_p xbeta=ps_xb stdxbeta=ps_sdxb predicted=ps_pred;
run;

data ps_weight;
set ps_p;
if group=1 then ps_weight=1/ps_pred;
else ps_weight=1/(1-ps_pred);
run;

proc means noprint data=ps_weight;


var ps_weight;
output out=q mean=mn_wt;

Raphaël Busson (Université de Caen) GNU General Public License 45


Aide SAS

run;

data ps_weight2;
if _n_=1 then set q;
retain mn_wt;
set ps_weight;
wt2=ps_weight/mn_wt; * Normalized weight;
run;

proc glm data=ps_weight2;


class group;
model outcome=group / ss3 solution;
weight wt2;
means group;
run;

13.3 Par la création de strates


La stratification par quintiles du score de propension permet d’éliminer environ 90% des biais. Cette
méthode n’assure pas l’équilibre au sein d’une même strate.

proc logistic descending data=table;


title 'Propensity Score Estimation';
model group=var1-var3/lackfit outroc=ps_r;
output out=ps_p xbeta=ps_xb stdxbeta=ps_sdxb predicted=ps_pred;
run;

proc rank data=ps_p out=ps_strataranks groups=5;


var ps_pred;
ranks ps_pred_rank;
run;

proc sort data=ps_strataranks;


by ps_pred_rank;

proc ttest;
by ps_pred_rank;
class group;
var outcome;
ods output statistics=strata_out;

data weights;
set strata_out;
if class='Diff (1-2)';
wt_i=1/(StdErr**2);
wt_diff=wt_i*Mean;

proc means noprint data=weights;

46 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

var wt_i wt_diff;


output out=total sum=sum_wt sum_diff;

data total2;
set total;
Mean_diff = sum_diff/sum_wt;
SE_Diff = SQRT(1/sum_wt);

proc print data=total2;


run;

13.4 Par l’appariement 1 :1


Dans le code suivant on utilise une méthode d’appariement caliper, il existe aussi les méthodes nearest
neighbor, mahalanobis metric... Le grand problème de cette méthode est la perte de sujets. En effet,
tous les sujets ne peuvent pas être appariés. Cela induit une perte de puissance et peut impliquer que les
conclusions ne soient pas généralisables à la population complète des patients. Les avantages sont que l’on
mime une randomisation et que l’on obtient une réduction très efficace des biais entre les deux les groupes
d’individus appariés.

proc logistic descending data=table;


title 'Propensity Score Estimation';
model group=var1-var3/lackfit outroc=ps_r;
output out=ps_p xbeta=ps_xb stdxbeta=ps_sdxb predicted=ps_pred;
run;

data one;
set ps_p;
ranvar=ranuni(0);

proc sort data=one;


by group ranvar;

proc transpose data=one out=data1;


by group;

data id_t (rename=(COL1-COL5 = tid1-tid5));


* Note: N of columns is number of obs in treatment group;
set data1; if group=1 and _NAME_='id';

data ps_t (rename=(COL1-COL5 = tps1-tps5));


set data1; if group=1 and _NAME_='ps_pred';

data id_c (rename=(COL1-COL8 = cid1-cid8));


* Note: N of columns is number of obs in control group;
set data1; if group=0 and _NAME_='id';

data ps_c (rename=(COL1-COL8 = cps1-cps8));

Raphaël Busson (Université de Caen) GNU General Public License 47


Aide SAS

set data1; if group=0 and _NAME_='ps_pred';

data all;
merge id_t ps_t id_c ps_c;
caliper=.10; * Note: caliper for matching is specified here;
array treat_id {*} tid1-tid5;
array ctl_id {*} cid1-cid8;
array treat_p {*} tps1-tps5;
array ctl_p {*} cps1-cps8;
array used_i {*} used1 - used8;
array matched_t {*} m_tid1-m_tid5;
array matched_c {*} m_cid1-m_cid5;
match_N=0;
do i=1 to 5;
min_diff=1;
best_match=0;
do j=1 to 8;
if used_i[j]=. then do;
if ABS(treat_p[i]-ctl_p[j])<caliper then do;
if ABS(treat_p[i]-ctl_p[j])<min_diff then do;
min_diff=ABS(treat_p[i]-ctl_p[j]);
best_match=j;
end;
end;
end;
end;
if best_match>0 then do;
match_N=match_N+1;
used_i[best_match]=1;
matched_t[match_N]=treat_id[i];
matched_c[match_N]=ctl_id[best_match];
end;
end;

data matches;
set all;
array matched_t {*} m_tid1-m_tid5;
array matched_c {*} m_cid1-m_cid5;
do match=1 to match_N;
Treatment_IDN=matched_t[match];
Control_IDN=matched_c[match];
output;
end;
keep match treatment_idn control_idn;

proc print;
var match treatment_idn control_idn;
title 'Matched Observations in Treatment and Control Groups';
run;

48 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

13.4.1 Macro appariement


SAS propose une macro qui réalise plusieurs méthodes d’appariements radius, caliper et nearest
available neighbor. J’ai rajouté quelques variables pour rendre la macro plus fonctionnelle. (Attention
sur le site de sas il y a deux erreurs dans la macro. Il est écrit Treatment à la place de
&datatreatment et Control à la place de &datacontrol respectivement dans la création des
tables _Treatment0 et _Control0.)

%let nom_table_sortie=; /*nom de la table de sortie avec les individus appariés*/


%let datatreatment=; /*table avec les sujets du premier groupe*/
%let idT=; /*Identifient des sujets du premier groupe*/
%let pscoreT=; /*Score de propension des sujets du premier groupe*/
%let datacontrol=; /*table avec les sujets du deuxième groupe*/
%let idC=; /*Identifient des sujets du deuxième groupe*/
%let pscoreC=; /*Score de propension des sujets du deuxième groupe*/
%let method=; /*methode utilise RADIUS, NN ou CALIPER*/
%let numberofcontrols=; /*nombre de témoins pour un cas*/
%let caliper=; /*ecart max entre les sujets appariés avec la metode caliper*/
%let replacement=; /*NO ou rien*/

%macro PSMatching(nom_table_sortie, idT, idC, pscoreT, pscoreC, datatreatment=,


datacontrol=, method=, numberofcontrols=, caliper=, replacement=);
/* Create copies of the treated units if N > 1 */
data _PSMatching_Treatment0(drop= i);
set &datatreatment; /*Treatment->&datatreatment*/
do i= 1 to &numberofcontrols;
RandomNumber= ranuni(12345);
output;
end;
run;
/* Randomly sort both datasets */
proc sort data= _PSMatching_Treatment0
out= _PSMatching_Treatment(drop= RandomNumber);
by RandomNumber;
run;
data _PSMatching_Control0;
set &datacontrol; /*Control->&datacontrol*/
RandomNumber= ranuni(45678);
run;
proc sort data= _PSMatching_Control0 out= _PSMatching_Control(drop= RandomNumber);
by RandomNumber;
run;
data &nom_table_sortie(keep = IdSelectedControl MatchedToTreatID);
length &pscoreC 8;
length &idC 8;
/* Load Control dataset into the hash object */
if _N_= 1 then do;
declare hash h(dataset: "_PSMatching_Control", ordered: 'no');
declare hiter iter('h');
h.defineKey("&idC");
h.defineData("&pscoreC", "&idC");

Raphaël Busson (Université de Caen) GNU General Public License 49


Aide SAS

h.defineDone();
call missing(&idC, &pscoreC);
end;
/* Open the treatment */
set _PSMatching_Treatment;
%if %upcase(&method) ~= RADIUS %then %do;
retain BestDistance 99;
%end;
/* Iterate over the hash */
rc= iter.first();
if (rc=0) then BestDistance= 99;
do while (rc = 0);
/* Caliper */
%if %upcase(&method) = CALIPER %then %do;
if (&pscoreT - &caliper) <= &pscoreC <= (&pscoreT + &caliper) then do;
ScoreDistance = abs(&pscoreT - &pscoreC);
if ScoreDistance < BestDistance then do;
BestDistance = ScoreDistance;
IdSelectedControl = &idC;
MatchedToTreatID = &idT;
end;
end;
%end;
/* NN */
%if %upcase(&method) = NN %then %do;
ScoreDistance = abs(&pscoreT - &pscoreC);
if ScoreDistance < BestDistance then do;
BestDistance = ScoreDistance;
IdSelectedControl = &idC;
MatchedToTreatID = &idT;
end;
%end;
%if %upcase(&method) = NN or %upcase(&method) = CALIPER %then %do;
rc = iter.next();
/* Output the best control and remove it */
if (rc ~= 0) and BestDistance ~=99 then do;
output;
%if %upcase(&replacement) = NO %then %do;
rc1 = h.remove(key: IdSelectedControl);
%end;
end;
%end;
/* Radius */
%if %upcase(&method) = RADIUS %then %do;
if (&pscoreT - &caliper) <= &pscoreC <= (&pscoreT + &caliper) then do;
IdSelectedControl = &idC;
MatchedToTreatID = &idT;
output;
end;
rc = iter.next();

50 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

%end;
end;
run;
/* Delete temporary tables. Quote for debugging */
proc datasets nolist;
delete _PSMatching_:(gennum=all);
run;
%mend PSMatching;
%PSMatching(nom_table_sortie=&nom_table_sortie, datatreatment=&datatreatment,
datacontrol=&datacontrol, method=&method,numberofcontrols=&numberofcontrols,
caliper=&caliper, replacement=&replacement, idT=&idT, idC=&idC,
pscoreT=&pscoreT, pscoreC=&pscoreC);

13.4.2 Appariement mahalanobis metric


On peut rajouté des variables pour le calcule de la distance. Cela peut être utile pour une variable qui
change les chances de guérison. Dans le code si dessous l’âge a été rajouté.

data _TreatControl;
set Treatment(rename=(idT= id pscoreT= pscore ageT= age))
Control(rename=(idC= id pscoreC= pscore ageC= age));
run;

proc princomp data= _TreatControl std out= _TreatControlDC;


var pscore age;
run;

data _Treatment0(rename=(prin1= pscoreT prin2= ageT id= idT))


_Control0(rename=(prin1= pscoreC prin2= ageC id= idC));
set _TreatControlDC;
RandomNumber= ranuni(123456);
if group= 1 then output _Treatment0;
else if group= 0 then output _Control0;
run;

proc sort data= _Treatment0 out= _Treatment;


by RandomNumber;
run;

proc sort data= _Control0 out= _Control;


by RandomNumber;
run;

data MatchedMH(keep = IdSelectedControl MatchedToTreatID);


length idC pscoreC ageC 8;
if _N_= 1 then do;
declare hash h(dataset: "_Control", ordered: 'no');
declare hiter iter('h');
h.defineKey('idC');

Raphaël Busson (Université de Caen) GNU General Public License 51


Aide SAS

h.defineData('pscoreC', 'idC', 'ageC');


h.defineDone();
call missing(pscoreC, idC, ageC);
end;
set _Treatment;
retain BestDistance 99;
rc=iter.first();
if (rc=0) then BestDistance= 99;
do while (rc = 0);
* Euclidean distance;
ScoreDistance = sqrt((pscoreT-pscoreC)**2 + (ageC-ageT)**2);
if ScoreDistance < BestDistance then do;
BestDistance = ScoreDistance;
IdSelectedControl = idC;
MatchedToTreatID = idT;
end;
rc = iter.next();
if (rc ~= 0) then do;
output;
rc1 = h.remove(key: IdSelectedControl);
end;
end;
run;

13.4.3 Global optimal algorithmes

proc sort data= Control out= _Control0;


by idC;
run;

data _Control;
set _Control0;
DistCol = compress('d' || _N_);
run;

data DistMatrix (keep= idT d1-d5);


length pscoreC 8;
length idC 8;
if _N_= 1 then do;
declare hash h(dataset: "_Control", ordered: 'ascending');
declare hiter iter('h');
h.defineKey('idC');
h.defineData('pscoreC', 'idC');
h.defineDone();
call missing(idC, pscoreC);
end;
set Treatment;

52 Raphaël Busson (Université de Caen) GNU General Public License


Aide SAS

array dis(*) d1-d5;


rc=iter.first();
if (rc=0) then i=1;
do while (rc = 0);
dis(i)= abs(pscoreT - pscoreC);
i+1;
rc = iter.next();
if (rc~=0) then output;
end;
run;

proc assign data=DistMatrix out= Result;


cost d1-d5;
id idT;
run;

proc print data= result;


sum _fcost_;
run;

proc sql;
create table MatchedOpt as
select b.idC as IDSelectedControl, a.idT as IDTreatment
from result a left join _Control b
on a._ASSIGN_ = b.DistCol;
quit;

13.5 Par l’ajout d’une co-variable


On mime moins bien un essai randomisé.

proc logistic descending data=table;


title 'Propensity Score Estimation';
model group=var1-var3/lackfit outroc=ps_r;
output out=ps_p xbeta=ps_xb stdxbeta=ps_sdxb predicted=ps_pred;
run;

proc glm data=ps_p;


class group;
model outcome=group ps_pred / ss3;
lsmeans group;
run;

Raphaël Busson (Université de Caen) GNU General Public License 53

Vous aimerez peut-être aussi