Annonce

Bienvenue sur le site support de mes ouvrages d'introduction à SAS

La 4ème édition de mon ouvrage est toujours disponible !

Où trouver cet ouvrage ?


#1 08-02-2021 17:26:52

SAS-SR
Administrateur
Lieu: Université d'Orléans
Date d'inscription: 01-09-2008
Site web

heatmap !

Bonjour

(en passant, quand je vois une heatmap, systématiquement, je pense à "heatwave" par Martha and the vandellas :
https://www.youtube.com/watch?v=d_9JyrPGLC4
fin de la parenthèse...)

ça vous dirait de comprendre comment construire ce joli graphique :
http://www.sas-sr.com/img/heatmap.png

que représente-t-il ? l'évolution depuis le début aout 2020 du taux de positivité hebdomadaire au test virologique covid-19 par région. Les région sont classées de haut en bas, de la région qui a connu le taux de positivité le plus élevé sur la période à la région qui a connu le taux le plus bas.

où récupérer les données ?
pour les résultats par région aux tests :
https://www.data.gouv.fr/fr/datasets/do … -covid-19/
il faut récupérer le fichier sp-pos-heb-reg-AAAA-MM-DD-19h20.csv

et pour la nomenclature des régions ici :
https://www.insee.fr/fr/information/4316069
il faut récupérer le fichier Liste des régions en CSV (fichiers region2020.csv)

Mais avant tout, il faut remercier Mathieu : c'est lui qui a écrit l'essentiel de ce code. Je ne suis intervenu que marginalement pour corriger quelques trucs qui me chiffonnaient...

On ne va pas tout voir aujourd'hui... je complèterai ce sujet au fur et à mesure...

on va commencer par créer une table... il y a beaucoup de données dans le fichier source, il va donc falloir écarter ce qui ne nous intéressera pas...

Code:

filename file "C:\intro_sas/fichiers/sp-pos-heb-reg-2021-02-07-19h20.csv";

data tests_vir (keep=reg week tauxpos p t);
   infile file dlm=";" firstobs=2 ;
   input reg :$2. week_ :$8. p_f p_h p t_f t_h t cl_age90 :$2. pop ;
   if substr(reg,1,1) ne '0' and cl_age90="0" ;
   week=input(compress(substr(translate(week_,"W ","S-"),3)),weekv5.);
   if month(week)>=8 or year(week)>=2021 ;
   tauxpos=round(100*p/t,0.01);
run;

voici les premières lignes du fichier CSV :

Code:

reg;week;P_f;P_h;P;T_f;T_h;T;cl_age90;pop
01;2020-S21;0;0;0;7;4;11;09;40134
01;2020-S21;1;0;1;13;27;40;19;50483
01;2020-S21;1;0;1;70;50;120;29;34558
01;2020-S21;1;0;1;37;37;75;39;37149

Pour chaque région (premier champ), pour chaque semaine (second champ), on dispose dans l'ordre du nombre de tests positifs pour les femmes, pour les hommes, en totalité, des tests passés par les femmes, les hommes, en totalité, de l'âge des personnes testées regroupées par classe d'âge. 09 correspond au 0-9 ans, 19 aux 10-19 ans etc.. 0 correspond à l'information tous âges confondus. Le dernier champ indique la population totale de la classe d'âge (il y a 40134 personnes âgées de moins de 10 ans dans la région 01).

Nous souhaitons conserver uniquement les informations relatives aux régions métropolitaines (les régions d'outre-mer débutent par un 0), postérieures au 1er aout, tous sexes confondus et tous âges confondus.

La transformation du second champ en une date SAS va nécessiter quelques acrobaties... Mathieu (et moi aussi) n'avons pas trouvé d'INFORMAT à même de transformer un champ comme 2020-S21 en une date SAS. En revanche, l'INFORMAT WEEKVw. sait interpréter 20W21 comme une date qui correspondra au lundi qui débute la 21ème semaine de 2020.

la fonction TRANSLATE va permettre de remplacer -S par W, on obtiendra alors 2020W21
au moyen de SUBSTR, on extrait du 3ème au 8ème caractère : on obtient alors 20W21
on peut alors demander via INPUT l'interprétation de 20W21 par l'INFORMAT WEEKV5. et obtenir une date SAS, nombre de jours depuis le 1er janvier 1960 correspondant au lundi qui débute la semaine 21. Mathieu fait appel à COMPRESS pour éviter de laisser trainer des blancs dans la chaine de caractères.

Au moyen de la condition suivante :

Code:

   if month(week)>=8 or year(week)>=2021 ;

On ne conservera que les données postérieures au 3/08/2020 (les données relatives aux 1er et 2 aout sont associées à une semaine qui débute en juillet - elles sont donc écartées).

Il nous reste à calculer un taux de positivité :

Code:

   tauxpos=round(100*p/t,0.01);

quelle sera notre étape suivante ?
calculer un taux de positivité pour chaque région sur la période.

je vous laisse y réfléchir mais en aucun cas, vous ne devez calculer une moyenne des taux de positivité...
soit un taux de positivité égal à 10% une semaine où vous avez eu 100 tests
et un taux de positivité égal à 5% une semaine où vous avez eu 10000 tests.

faites une moyenne simple, vous obtenez 7.5% et vous vous direz sûrement que ce résultat est notoirement faux...

à suivre

Hors ligne

 

#2 09-02-2021 16:28:10

SAS-SR
Administrateur
Lieu: Université d'Orléans
Date d'inscription: 01-09-2008
Site web

Re: heatmap !

Avançons...

pour calculer les taux de positivité sur la période pour chaque région, nous allons exécuter ce programme :

Code:

proc sql ;
create table tempbis as 
            select reg,
                     round(100*p/t,0.01) as taux_moyen
    from (select reg, sum(p) as p,sum(t) as t 
           from tests_vir
           group by reg)
    order by taux_moyen desc ; 
quit;

Il fallait bien entendu pour chaque région sommer sur la période le nombre de tests effectués et le nombre de cas positifs (c'est ce qu'effectue la sous requête) avant de calculer le taux de positivité dans la requête principale.

Vous remarquez qu'on demande un tri par taux moyen décroissant. La suite du programme devrait commencer à vous expliquer pourquoi...

Code:

data tempbis;
   set tempbis;
   ordre+1;
run;

en fait, c'est la variable ORDRE qui sera représentée sur l'axe Y. Lorsque l'on souhaite ordonner d'une façon particulière les valeurs sur un certain axe, le plus simple est toujours de créer cet ordre au moyen d'une variable puis de créer un FORMAT qui permette l'affichage de ce que vous souhaitez voir apparaître.

Si on avait simplement demandé à avoir les intitulés des régions, ils auraient été présentés dans l'ordre alphabétique (et nous aurions ainsi perdu une information... et notre graphique aurait été moins joli...)

Vous devinez à ce stade que nous aurons prochainement à créer un FORMAT à appliquer à la variable ORDRE et qui permettra l'affichage du noms des régions.

Avant cela, il nous reste à intégrer la variable ORDRE à notre table contenant les données :

Code:

proc sql ;
create table tests_vir2 as select * 
   from tests_vir natural inner join tempbis order by ordre desc, week;
quit;

Nous aurons en fait deux FORMAT à créer... le premier, comme annoncé pour présenter les intitulés des régions et le second pour afficher sur l'axe des X les différentes semaines représentées sous la forme "03/08/20 - 09/08/20" pour la semaine qui débutait le lundi 3 aout 2020.

Nous verrons cela la prochaine fois...

à suivre

Hors ligne

 

#3 16-02-2021 11:17:24

SAS-SR
Administrateur
Lieu: Université d'Orléans
Date d'inscription: 01-09-2008
Site web

Re: heatmap !

Reprenons...

Vous allons déjà créer le premier FORMAT qui va nous permettre de représenter les différentes semaines sous la forme indiquée plus haut.

nous allons commencer par ça:

Code:

proc sql;
   select min(week),max(week) into :minda,:maxda from tests_vir2;
quit;

la variable WEEK porte assez mal son nom... elle a en effet pour modalité une date SAS, nombre de jours depuis le 1er janvier 1960, qui correspond au lundi qui débute une semaine. Au moyen de PROC SQL, nous sauvegardons les valeurs minimale et maximale de WEEK dans deux macro-variables.

et bien entendu, nous allons utiliser ces macro-variables...

Code:

data form ;
   retain fmtname "datesem" type "n" ;
   length label $ 50; 
      do start=&minda to &maxda by 7 ;
         label=compbl(put(start,ddmmyy8.)||' - '||put(start+6,ddmmyy8.));
         output;
      end;
run;

à la lecture de ce programme, vous devez vous dire "tiens... il construit une table CNTLIN". Notre FORMAT aura pour nom DATESEM, c'est un FORMAT numérique (TYPE 'n').

au moyen d'une boucle allant de la date minimum à la date maximum, avec un pas de 7, nous allons pour chaque valeur de WEEK (pour chaque lundi débutant une semaine), construire la valeur de LABEL comme étant la concaténation de la date débutant la semaine présenté au moyen du FORMAT DDMMYY8., d'un tiret et de la date qui clôt la semaine, (la date de début + 6 jours) présentée elle aussi au moyen du FORMAT DDMMYY8.

nous faisons appel à la fonction COMPBL par sécurité, pour éviter que plusieurs blancs se suivent dans la concaténation ainsi construite (il faudra vérifier mais c'est très certainement en fait inutile...).

Ensuite, il ne nous reste plus qu'à créer notre FORMAT :

Code:

proc format cntlin=form;
run;

à suivre...

Hors ligne

 

#4 25-02-2021 15:43:37

SAS-SR
Administrateur
Lieu: Université d'Orléans
Date d'inscription: 01-09-2008
Site web

Re: heatmap !

reprenons...

nous avons un second FORMAT à créer : celui qui va associé le rang de la région dans le classement des régions les plus impactées par la COVID avec le nom de la région.

Commençons par créer une table contenant le nom des régions :

Code:

data region(keep=reg label);
infile "C:\intro_sas/fichiers/region2020.csv" 
       firstobs=2 encoding="utf-8" dsd ;
input reg :$2. x1 $ x2 $ x3 $ label :$40. x5 $ ;
run;

(le lien vers le fichier region2020.csv est précisé dans le premier post).

voici un extrait de la table obtenue :

Code:

reg    label

01     Guadeloupe
02     Martinique
03     Guyane
04     La Réunion
06     Mayotte
11     Île-de-France
24     Centre-Val de Loire
27     Bourgogne-Franche-Comté
28     Normandie
32     Hauts-de-France
44     Grand Est
52     Pays de la Loire
53     Bretagne
75     Nouvelle-Aquitaine
76     Occitanie

rappelons nous maintenant que nous avons créé, il y a quelques temps, une table TEMPBIS. Jetons un oeil à cette table :

Code:

       taux_
reg    moyen    ordre

84     10.18       1
27      8.46       2
32      8.13       3
11      7.91       4
93      7.27       5
24      6.93       6
28      6.49       7
44      6.43       8
76      6.40       9
52      5.83      10
75      5.47      11
53      4.53      12
94      3.23      13

les codes des régions sont bien entendu identiques entre la table TEMPBIS et la table REGION. Fusionnons ces deux tables :

Code:

proc sql ;
   create table form2 as select * from tempbis natural left join region;
quit;

et regardons le contenu de cette table :

Code:

                                     taux_
reg    label                         moyen    ordre

11     Île-de-France                  7.91       4
24     Centre-Val de Loire            6.93       6
27     Bourgogne-Franche-Comté        8.46       2
28     Normandie                      6.49       7
32     Hauts-de-France                8.13       3
44     Grand Est                      6.43       8
52     Pays de la Loire               5.83      10
53     Bretagne                       4.53      12
75     Nouvelle-Aquitaine             5.47      11
76     Occitanie                      6.40       9
84     Auvergne-Rhône-Alpes          10.18       1
93     Provence-Alpes-Côte d'Azur     7.27       5
94     Corse                          3.23      13

Nous disposons maintenant d'une bonne base pour créer une table CNTLIN puisqu'on sait, par exemple, que la région dans laquelle le taux est le plus élevé sur la période est Auvergne-Rhône-Alpes (vous pouvez avoir des taux moyens différents des miens si vous utilisez un autre fichier source que le mien...)

quelques modifications :

Code:

data form2;
  set form2;
  rename ordre=start ;
  retain fmtname "region" type "n";
run;

proc format cntlin=form2;
run;

et vous disposez de votre FORMAT !

à suivre...

Hors ligne

 

#5 02-03-2021 07:15:55

SAS-SR
Administrateur
Lieu: Université d'Orléans
Date d'inscription: 01-09-2008
Site web

Re: heatmap !

il ne nous reste plus qu'à construire le graphique.

Il faut déjà construire une table qui va nous permettre de définir les couleurs à employer - il faudra ensuite utiliser l'option RATTRMAP de PROC SGPLOT.

(voir cet article pour plus d'informations)
 

Code:

data rangemapdata;
   retain id "myid";
   input min :$2. max :$5. colormodel1 :$6. colormodel2 :$11.;
datalines;
0 5 green yellow
5 10 yellow red
10 _max_ red black
;

et, enfin, le PROC SGPLOT qui va créer notre graphique :

Code:

ods graphics / height=15cm width=25cm imagemap;

title "Évolution du taux de positivité des tests virologiques par région et par semaine";
proc sgplot data=tests_vir2 rattrmap=rangemapdata;
   heatmap x=week y=ordre / discretex discretey colorresponse=tauxpos 
                            rattrid=myid outline outlineattrs=(color=white) 
                            tip=(colorresponse) tiplabel=("Taux ");
   xaxis display=(nolabel) valuesrotate=diagonal2;
   yaxis display=(nolabel);
   label week="Semaine" tauxpos="Taux de positivité";
   format ordre region. week datesem.;
run;

et voilà !

ce sujet est maintenant terminé... à bientôt pour un nouveau sujet des beaux mercredis...

Hors ligne

 

Pied de page des forums

Propulsé par FluxBB
Traduction par FluxBB.fr
Flux RSS