![]()
Analyser ses données écologiques en SAS
![]()
Dernière modification : 27/11/04
Les fonctions sont des actions déja préprogrammées que l'utilisateur peut appeler dans l'étape DATA pour effectuer des calculs sur des variables. Elles sont généralement définie par nom (à ne pas utiliser pour définir des noms de variables) et un ou plusieurs arguments séparés par une virgule "," (en Excel = ";").
Par exemple, le code lognind = log(nind); calcule le logarithme népérien du contenu de la variable nind et le stocke dans la variable lognind. On aurait pu le stocker dans la variable nind en écrivant nind = log(nind); mais on perdait alors l'abondance originale. On peut aussi écrire directement des chiffres ou du texte à la place d'un nom de variable. On peut emboîter les fonctions les unes dans les autres en les utilisant comme argument d'autres fonctions ou utiliser comme argument des calculs entre différentes variables. Par exemple, nom=compress(upcase(nom)); transforme d'abord le contenu de la variable nom en majuscule, puis élimine tous les caractères blancs qu'elle contient. Les fonctions sont sensibles au type numérique ou alphanumérique des variables.
Les fonctions peuvent être rassemblées en différentes familles et on présente ci-dessous une liste des plus fréquement utilisées. On indiquera le type de l'argument par le code num pour une variable ou un contenu numérique, le code anum pour une variable ou un contenu alphanumérique et le code variable pour indiquer un nom de variable.
Les fonctions sont rassemblées par différents types :
ABS(num) donne la valeur absolue (= la valeur positive) d'un nombreABS(5.8) => 5.8 ou ABS(-58) => 58DIM(variable) donne le nombre d'éléments qu'il y a dans un ARRAY
si on a défini ARRAY temp (*) x1-x5, alors DIM(temp) => 5MAX(num1, ..., numn) calcule la valeur maximale de la liste de chiffres ou de variables (voir aussi l'introduction des variables statistiques où d'autres modes d'expression de listes de variables sont proposés)
MAX(1.5, 1.8, 1.79999) => 1.8MIN(num1, ..., numn) calcule la valeur minimale de la liste de chiffres ou de variables (voir aussi l'introduction des variables statistiques où d'autres modes d'expression de listes de variables sont proposés)
MIN(1.5, 1.8, 1.79999) => 1.5MOD(num1, num2) calcule le reste de la division de num1 par num2
MOD(10, 3) => 1SQRT(num) calcule la racine carré d'un nombre. Pour d'autres racines, on procèdera avec un exposant fractionnaire comme x = y ** (1/3) pour obtenir une racine cubique.
SQRT(9) => 3
CEIL(num) arrondi à l'entier supérieurCEIL(5.8) => 6FLOOR(num) arrondi à l'entier inférieur
FLOOR(5.8) => 5INT(5.8) => 5ROUND(num, nombre) arrondi le nombre num en fonction du nombre d'unités d'arrondi
ROUND(5.8, 1) => 6
ROUND(5.8) => 6
ROUND(5.7999, 0.1) => 5.8
ROUND(57899.1,10) => 57900
EXP(num) calcule l'exposant de numEXP(1) => 2.7182818285
EXP(0) => 1
EXP(3.123) => 22.714420793LOG(num) calcul le logarithme népérien de num
LOG(1) => 0
LOG(0) => . et cela génére un message d'erreur
LOG (0.5) => -0.693147181
LOG(12) => 2.4849066498
LOG(EXP(1)) => 1Pour effectuer une transformation logarithmique d'abondances d'espèces dont les valeurs peuvent être nulles, on ne peut appliquer directement la formule logabond => LOG(abond). Il faut donc ne le calculer pour pour les abondances >= à 1 ou effectuer systématiquement la transformation suivante : logabond = LOG(abond +1).
LOG2(num) calcul le logarithme en base 2 de num
LOG2(1) => 0
LOG2(0) => . et cela génére un message d'erreur
LOG2 (0.5) => -1
LOG2(12) => 3.5849625007
LOG2(2) => 1LOG10(num) calcul le logarithme en base 10 de num
LOG10(1) => 0
LOG10(0) => . et cela génére un message d'erreur
LOG10(0.5) =>-0.301029996
LOG10(12) => 1.079181246
LOG10(2) => 1Formules pour les autres bases = ?
Les arguments des fonctions trigonométriques utilisant des degrés sont spécifiés en radians. 180 degrés = 1 pi radian. Donc, à partir d'un angle en degré, l'angle en radian se calcule comme suit :Angle en radian = pi * (angle en degré) / 180
avec pi = 3.14159265358979COS(num) calcule le cosinus de num
si pi = 3.14159265358979COS( 0 / 180 * pi) => 1.000 pour 0 degré
COS( 45 / 180 * pi) => 0.707 pour 45 degrés
COS( 90 / 180 * pi) => 0.000 pour 90 degrés
COS(180 / 180 * pi) => -1.000 pour 180 degrés
COS(270 / 180 * pi) => 0.000 pour 270 degrés
COS(360 / 180 * pi) => 1.000 pour 360 degrésSIN(num) calcule le sinus de numsi pi = 3.14159265358979SIN( 0 / 180 * pi) => 0.000 pour 0 degré
SIN( 45 / 180 * pi) => 0.707 pour 45 degrés
SIN( 90 / 180 * pi) => 1.000 pour 90 degrés
SIN(180 / 180 * pi) => 0.000 pour 180 degrés
SIN(270 / 180 * pi) => -1.000 pour 270 degrés
SIN(360 / 180 * pi) => 0.000 pour 360 degrésTAN(num) calcule la tangente de num
Pour les fonctions ARC qui permettent d'obtenir l'inverse d'un cosinus, d'un sinus ou d'une tangente, num est un chiffre compris entre 0 et 1 et le résultat est exprimé en radian. Pour l'obtenir en degré, il faut effectué la transformation suivante :
Angle en degré = 180 * (angle en radian) / pi
avec pi = 3.14159265358979ARCOS(num) calcule l'arcosinus de num (qui est un nombre entre 0 et 1). C
ARSIN(num) calcule l'arcsinus de num
ARTAN(num) calcule l'arctangente de num
Pour les fonctions hyperboliques, l'argument num est simplement numérique.
COSH(num) calcule le cosinus hyperbolique de num [c'est en fait le résultat de (exp(num) + exp(-num))/2]
SINH(num) calcule le sinus hyperbolique de num [c'est en fait le résultat de (exp(num) - exp(-num))/2]
TANH(num) calcule la tangente hyperbolique de num [c'est en fait le résultat de [SINH/COSH]
Ces différentes fonctions calculent des paramètres statistiques sur la distribution des valeurs ou de la liste des variables. Les arguments peuvent donc être une liste de chiffres ou de variables séparées par des virgules mais aussi être exprimés sous la forme d'une liste décrite par OF var1-varn. Par exemple, écrire somme = SUM(x1, x2, x3, ...à compléter...,x120) peut aussi bien s'écrire somme = SUM (OF x1-x120). L'expression "OF" est indispensable pour SAS n'interprète pas le signe "-" comme une soustraction de deux variables.Si un ARRAY est défini (ARRAY y(*) x1-X120), on peut aussi l'utiliser somme= SUM(OF y(*)). Si on ne dispose pas d'ARRAY ou de listes de noms de variables du style x1-x1120, on peut aussi donner la liste des variables selon la forme premierevar--dernierevar qui utiliser, selon leur ordre de création, toutes les variables comprises entre la premierevar et la dernierevar, celles-ci incluses. Pratique quand les noms des varaibles sont des noms de stations ou des abréviations de taxons.
N(num1, ..., numn) calcule la fréquence de valeurs non-manquantes
N(1, 2, 4, 8, 10, 8, 4, 2, 1) => 9NMISS(num1, ..., numn) calcule la fréquence des valeurs manquantes
NMISS(1, 2, 4, 8, 10, 8, 4, 2, 1) => 0SUM(num1, ..., numn) calcule la somme de la liste des arguments non-manquants
SUM(1, 2, 4, 8, 10, 8, 4, 2, 1) => 40MEAN(num1, ..., numn) calcule la moyenne de la liste des arguments non-manquants
MEAN(1, 2, 4, 8, 10, 8, 4, 2, 1) => 4.44RANGE(num1, ..., numn) calcule l'écart entre les valeurs minimale et maximale de la liste des arguments non-manquants
RANGE(1, 2, 4, 8, 10, 8, 4, 2, 1) => 9STD(num1, ..., numn) calcule l'écart-type de la liste des arguments non-manquants
STD(1, 2, 4, 8, 10, 8, 4, 2, 1) => 3.40STDERR(num1, ..., numn) calcule l'erreur-standard à la moyenne de la liste des arguments non-manquants
STDERR(1, 2, 4, 8, 10, 8, 4, 2, 1) => 1.13VAR(num1, ..., numn) calcule la variance de la liste des arguments non-manquants
VAR(1, 2, 4, 8, 10, 8, 4, 2, 1) => 11.53CV(num1, ..., numn) calcule le coefficient de variation de la liste des arguments non-manquants
CV(1, 2, 4, 8, 10, 8, 4, 2, 1) => 76.39CSS(num1, ..., numn) calcule la somme corrigée des carrés de la liste des arguments non-manquants
CSS(1, 2, 4, 8, 10, 8, 4, 2, 1) => 92.22
Ces fonctions permettent de calculer des probabilités d'occurrences d'évenements en fonction de différents types de distribution de valeur.PROBNORM(x) calcule la probabilité qu'une observation d'une distribution normale standardisée (avec une moyenne = 0 et écart-type = 1) soit plus petite ou égale à x.
PROBNORM(0) => 0.500 soit à la moyenne, la probabilité est de 50%
PROBNORM(1.96) => 0.9750 soit à la valeur de 1.96, à pratiquement 2 écart-types, la probabilité est de 97,5%PROBT(x, dld) calcule la probabilité qu'une observation d'une distribution de t de Student, avec ddl degré de liberté soit plus petite ou égale à x. Si on veut obtenir le niveau de signification d'un test de t bilateral, on doit faire p = (1 - PROBT(ABS(x),ddl))*2. Dans le cas d'un test unilatéral, on fera p = 1 - PROBT(ABS(x),ddl). On peut ainsi reconstruire un tableau de probabilité complet pour la v.a. de Student.
PROBT(1.45, 10) => 0.9112. La probabilité unilatérale est égale à 8,88 %; si le test est bilatéral, la probabilité est égale à 17,72 %
PROBT(1.96, 1000) => 0.9748. La probabilité unilatérale est égale à 2,52 %; si le test est bilatéral, la probabilité est égale à 5,04 %PROBF(x, ddln, ddld) calcule la probabilité qu'une observation d'une distribution de Fisher, avec ddln degré de liberté au numérateur (effet factoriel) et ddld degré de liberté au dénominateur (effet résiduel) soit plus petite ou égale à x. Si on veut obtenir le niveau de signification d'un test de F, on doit faire p = 1 - PROBF(x, ddln, ddld).
PROBF(3.32, 2, 3) => 0.8264. La probabilité est égale à 17,36 %PROBCHI(x, ddl) calcule la probabilité qu'une observation d'une distribution de Chicarré, avec ddl degré de liberté soit plus petite ou égale à x. Si on veut obtenir le niveau de signification d'un test de Chicarré, on doit faire p = 1 - PROBCHI(x, ddl).
PROBCHI(11.264, 11) => 0.5786. La probabilité est égale à 42,14 %Si on souhaite mesurer la fidelité d'une espèce de papillon à une plante, on peut utiliser le test de Chicarré avec par exemple le tableau suivant :
Fréquence observée
Papillon présent Papillon absent Plante présente
24 15 Plante absente
10 34
Fréquence attendue
Papillon présent Papillon absent Plante présente
15.98 23.02 Plante absente
18.02 25.98 Le Chicarré(r-1)*(c-1) = Chicarré(2-1)*(2-1) = Chicarré(1) = 12.88
PROBCHI(12.88, 1) => 0.99967. La probabilité unilatérale est égale à 0.0003, la relation est donc largement significative puisqu'on a 3 chances sur 10.000 de se tromper en disant qu'elle est vraie.
POISSON(x, n) calcule la probabilité qu'une observation d'une distribution de Poisson de moyenne x, soit plus petite ou égale à n.
POISSON(1, 2) => 0.9197PROBBNML(p, n, m) calcule la probabilité qu'une observation d'une distribution binomiale, avec une probabilité de succès p, un nombre d'essais n et un nombre de succès m, est plus petite ou égale à m.
PROBBNML(0.5, 10, 4) => 0.3770Les 3 fonctions suivantes font l'inverse des précédentes. Elles donnent les valeurs des tables qui correspondent à une probabilité et un certain nombre de degré de liberté.
TINV (p, ddl) calcule une valeur d'une table de t de Student correspondante à une probabilité p et ddl degré de liberté.
TINV(0.95, 2) => 2.9199FINV (p, ddln, ddld) calcule une valeur d'une table de F correspondante à une probabilité p et ddln degré de liberté au numérateur et ddld degré de liberté au dénominateur.
FINV(0.95, 2, 10) => 4.1028CINV (p, ddl) calcule une valeur d'une table de Chicarré correspondante à une probabilité p et ddl degré de liberté.
CINV(0.95, 3) => 7.81
Ces fonctions permettent de générer des nombres qui suivent différentes distributions qui peuvent être ensuite utilisées pour tester le comportement de différents modèles. Ces nombres ne sont pas à strictement parler purement aléatoires mais le nombre d'itérations nécessaires pour retrouver les mêmes séries est très très grand.Ces fonctions ont besoin d'un nombre de départ (n) qui permet de regénérer la même distribution de valeurs à condition qu'il soit plus grand que zéro. Si on utilise toujours le même nombre 5, la série de valeurs aléatoires générées sera la même à chaque exécution du programme. Si on utilise le chiffre zéro comme nombre de départ, c'est un nombre généré par l'horloge interne de l'ordinateur qui sert de point de départ et il est impossible d'obtenir les mêmes séries de nombres aléatoires. Les résultats peuvent alors varier d'une exécution à l'autre.
UNIFORM(n) génére un nombre pseudo-aléatoire compris entre 0 et 1 [ UNIFORM (n) est synonyme de RANUNI (n)]
NORMAL(n) génére un nombre dont la fréquence suit une distribution normale standardisée (avec une moyenne = 0 et écart-type = 1) [ NORMAL (n) est synonyme de RANNOR (n)].
Pour générer une série de valeurs x correspondant à une variable aléatoire normale de moyenne mean et un écart-type std, on utilisera la formule x = mean + std * NORMAL(0)
RANPOI(n, lambda) génére un nombre dont la fréquence suit une distribution de Poisson de moyenne lambda.
RANBIN(n, nbr, p) génére un nombre dont la fréquence suit une distribution binomiale(nbr, p).
COMPRESS(anum) enlève les blancs dans la chaîne de caractères anum. Si elle est utilisée avec deux arguments comme COMPRESS(anum, "%"), elle enlève les "%" dans la chaîne de caractères anum.COMPRESS("C'est la vie") => "c'estlavie"
COMPRESS("C'est la vie", "e") => "c'st la vi"LEFT(anum) aligne à gauche dans la chaîne de caractères anum.
LEFT(" C'est la vie ") => "c'est la vie "RIGHT(anum) aligne à droite dans la chaîne de caractères anum.
LEFT(" C'est la vie ") => " c'est la vie"TRIM(anum) enlève les blancs à droite (à la fin) dans la chaîne de caractères anum.
TRIM(" C'est la vie ") => " c'est la vie"Exemple comparatif de l'utilisation de ces 4 fonctions :
DATA; fonction="normal "; chaine=" ABCDE FGHIJ "; resultat='***'||chaine||'***'; OUTPUT; fonction="compress"; resultat='***'||COMPRESS(chaine)||'***'; OUTPUT; fonction="trim"; resultat='***'||TRIM(chaine)||'***'; OUTPUT; fonction="left"; resultat='***'||LEFT(chaine)||'***'; OUTPUT; fonction="right"; resultat='***'||RIGHT(chaine)||'***'; OUTPUT; fonction="trim(left)"; resultat='***'||TRIM(LEFT(chaine))||'***'; OUTPUT; RUN; PROC PRINT; OBS FONCTION CHAINE RESULTAT 1 normal ABCDE FGHIJ *** ABCDE FGHIJ *** 2 compress ABCDE FGHIJ ***ABCDEFGHIJ*** 3 trim ABCDE FGHIJ *** ABCDE FGHIJ*** 4 left ABCDE FGHIJ ***ABCDE FGHIJ *** 5 right ABCDE FGHIJ *** ABCDE FGHIJ*** 6 trim(left) ABCDE FGHIJ ***ABCDE FGHIJ***
TRANSLATE(anum, t1, f1, ..., tn, fn) traduit dans la chaîne de caractère anum les caractères f par le caractère t correspondant. Attention, ordre inverse de ce qu'on ferait logiquement, d'abord le nouveau puis l'ancien !
TRANSLATE(" C'est la vie ", "*", " ") => "****C'est la vie****"UPCASE(anum) transforme tous les caractères de la chaîne de caractère anum en majuscules.
UPCASE("C'est la vie") => "C'EST LA VIE"LOWCASE(anum) transforme tous les caractères de la chaîne de caractère anum en minuscules.
LOWCASE("C'est la vie") => "c'est la vie"REVERSE(anum) renverse lo'rdre de tous les caractères de la chaîne de caractère anum.
REVERSE("C'est la vie") => "eiv al tse'C"LENGTH(anum) donne la longueur de la chaîne de caractère anum en ignorant les caractères blancs à la fin de la chaîne.
LENGTH("C'est la vie ") => 12INDEX(anum, string) cherche dans la chaîne de caractère anum la position de la chaîne ou du caractère string.
INDEX("C'est la vie ", "v") => 10 INDEX("C'est la vie ", "z") => 0INDEXC(anum, t1, ..., tn ) cherche dans la chaîne de caractère anum la position d'un des caractères t.
INDEXC("C'est la vie ", "t", "l", "z") => 5SUBSTR(anum, n, m) extrait dans la chaîne de caractère anum m caractères en commençant à la position n.
SUBSTR("C'est la vie", 7, 2) => "la" SUBSTR("C'est la vie", 7) => "la vie" !SCAN(anum, n) extrait dans la chaîne de caractère anum le nième mot séparé par des blancs.
SCAN("C'est la vie", 2) => "la"SCAN(anum, n, car) extrait dans la chaîne de caractère anum le nième mot séparé par le délimiteur car.
SCAN("C'est_la_vie", 2, "_") => "la"
LAG n (anum) restitue la valeur qu'avait l'argument à la n ième ligne précédente.
Si on dispose d'un data set avec une colonne de chiffres sur 5 lignes.
DATA; INPUT x @@; y = LAG1(x); z = LAG2(x); CARDS; 1 2 3 4 5 6 ; PROC PRINT; RUN;OBS X Y Z1 1 . . 2 2 1 . 3 3 2 1 4 4 3 2 5 5 4 3 6 6 5 4DIF n (arg) fournit la valeur de la différence entre l'argument et la valeur qu'avait l'argument à la n ième ligne précédente.
y = DIF3(x) est égal à y = x - LAG3(x);
Les dates peuvent se gérer comme des chaînes de caractères mais on ne peut alors les classer dans un ordre chronologique. On peut répartir les jours, les mois et les années dans trois variables séparées mais se pose alors le problème du calcul des intervalles entre deux dates. SAS propose donc un format numérique spécial pour la gestion des dates. Ce format de type "date" est attribué lors de la lecture des variables avec un format de lecture spécial qui va traduire les informations "jour", "mois" et "année" sous la forme d'un nombre correspondant au nombre de jours écoulés depuis le 1er janvier 1960. La date est donc traduite en un nombre de jours qui peut alors être utilisé facilement pour calculer des intervalles, ordonner, ... Si on n'utilise pas de format de date particulier lors de l'impression, c'est d'ailleurs ce nombre de jours qui figurera sur les listings.
Il en existe de plusieurs sortes de format de lecture des dates :
DATEn. qui permet de lire une date représentée sous format alphanumérique
INPUT date1 DATE10.; CARDS; 1JAN1982 01 JAN 82 1 JAN 82 1-JAN-82 ;est lu convenablement et traduit par la valeur 8036 pour les 4 lignes de la variable date1.
DDMMYYn. qui permet de lire une date représentée sous format numérique
INPUT date1 DDMMYY8.; CARDS; 151082 15-10-82 15/10/82 ;est lu convenablement et traduit par la valeur 8323 pour les 3 lignes de la variable date1. Les formats MMDDYYn. et YYDDMMn. sont aussi disponibles.
Ces formats peuvent aussi être utilisé pour imprimer dans les listings ou dans les dates sauvées sous la forme d'un nombre de jours depuis le 1er janvier 1960. Par exemple,
PUT date1 DATE5. => 15OCT PUT date1 DATE6. => 15OCT PUT date1 DATE7. => 15OCT82 PUT date1 DATE8. => 15OCT82 PUT date1 DATE9. => 15OCT1982 PUT date1 DDMMYY2. => 15 PUT date1 DDMMYY8. => 15/10/82 PUT date1 MMDDYY8. => 10/15/82Différentes fonctions chronologiques sont disponibles :
DATE() ou TODAY() donne la date du jour.
TIME() donne l'heure du jour.date1 = TODAY() => date1 = 15763 si on est le 27 février 2003.heure1 = time() => heure1 = 46024.94 si il est 12 h 47' 4.9410"MDY(mois, jour, annee) transforme les informations d'une date stockée en trois variables en une nouvelle variable de type "date".
date1 = MDY( 8, 18, 1961) => date1 = 595.DAY(date), MONTH (date) et YEAR(date) transforme les informations de date stockée en une variable de type "date" en trois nouvelles variables.
date1 = TODAY() => date1 = 15763 si on est le 27 février 2003. jour = DAY(date1) => jour = 27 mois = MONTH(date1) => mois = 2 annee = YEAR (date1) => annee = 2003HMS(heure, minute, seconde) transforme les informations d'une heure stockée en trois variables en une nouvelle variable de type "heure".
heure1 = HMS( 12, 18, 10.01) => heure1 = 44290.01HOUR(heure), MINUTE (heure) et SECOND(heure) transforme les informations d'heure stockée en une variable de type "heure" en trois nouvelles variables.
heure1 = TIME() => heure1 = 46040.07 si il est 12 h 47' 20,07" heure = HOUR(heure1) => heure = 12 jour = MINUTE(heure1) => minute = 47 seconde = SECOND(heure1) => seconde = 20.07
![]()